Welcome to SIMPL Programming for Python
Lesson #5

Course content Enter chat room Send email 
to mailing list
Check calendar

Lesson Overview

In this lesson we are going to examine the detailed workings of a C sending  program and a python gui-based receiving program.

The sender program is able to send three different types of messages and the receiver program to receive these messages and react appropriately.
The sender program in this lesson has a textual interface. The sending of the various messages are initiated by running the program and varying the command line.
The messages are exactly the same as in Lessons #2, #3 and #4.
The receiver program prints to screen the various components of the messages received.

With this algorithm, we hope to demonstrate the following:
1. how a C simpl sender program can be made to initiate communications with a Python gui-based simpl receiver program.
 
 

Note:

Do NOT cut and paste the following code pieces. The scripts are available in the .../src directory for you to run directly.

 
 

Let's examine the sending program.

1. /*
2. FILE: sender.c
3. DESCRIPTION: : This is a C simpl sender.
4. Refer to lesson #5.
5. USAGE: sender tokenType
6. */
7.
8. // include required headers
9. #include <stdio.h>
10. #include <stdlib.h>
11. #include <string.h>
12. #include <simpl.h>
13.
14. // define possible message structures
15. typedef struct
16.     {
17.     int token;
18.     int var1;
19.     int var2;
20.     int var3;
21.     } MSG1;
22.
23. typedef struct
24.     {
25.     int token;
26.     float var1;
27.     } MSG2;
28.
29. typedef struct
30.     {
31.     int token;
32.     int var1;
33.     char var2[34];
34.     } MSG3;
35.
36. int main(int argc, char **argv)
37. {
38. char *me = "SENDER";
39. int receiver;
40. char mem[1024];
41.  int ret;
42. int size;
43. int type;
44. MSG1 *out1;
45. MSG2 *out2;
46. MSG3 *out3;
47 void *ptr;
48.
49. // check for correct number of command line arguments 
50. if (argc != 2)
51.     {
52.     printf("%s: incorrect number of command line\n", me);
53.     exit(-1);
54.     }
55.
56. // ascertain the token type
57. type = atoi(argv[1]);
58.
59. // compose the outgoing message based on the token type
60. if (type == 10)
61.     {
62.     out1 = (MSG1 *)mem;
63.     out1->token = 10;
64.     out1->var1 = 99;
65.     out1->var2 = 999;
66.     out1->var3 = 9999;
67.     ptr = out1;
68.     size = sizeof(MSG1);
69.     }
70. else if (type == 20)
71.     {
72.     outt2 = (MSG2 *)mem;
73.     out2->token = 20;
74.     out2->var1 = 3.1415; 
75.     ptr = out2;
76.     size = sizeof(MSG2);
77.     }
78. else if (type == 30)
79.     {
80.     out3 = (MSG3 *)mem;
81.     out3->token = 30;
82.     out3->var2 = 34;
83.     memcpy(out3->var2, "We are the knoghts who say Neeee.", 34);
84.     ptr = out3;
85.     size = sizeof(MSG3);
86.     }
87. else
88.     {
89.     printf("%s: incorrect token type\n", me);
90.     exit(-1);
91.     }
92.
93. // name attach this program
94. if (name_attach(me, NULL) == -1)
95.     {
96.     printf("%s: cannot attach name-%s\n", me whatsMyError());
97.     exit(-1);
98.     }
99. 
100. // name locate the receiving program
101. receiver = name_locate("RECEIVER");
102. if (receiver == -1)
103.     {
104.     printf("%s: cannot locate receiver-%s\n", me, whatsMyError());
105.     exit(-1);
106.     }
107.
108. // send the message to the receiving program
109. ret = Send(receiver, ptr, NULL, suze, 0);
110. if (ret == -1)
111.     {
112.     printf("%s: send error-%s\n", me, whatsMyError());
113.     exit(-1);
114.     }
115.
116. return(0);
117. }

Lines 9-12 include the required C header files. Note the inclusion of simpl.h.
Lines 15-21 define the binary message that corresponds to token value 10.
Lines 23-27 define the binary message that corresponds to token value 20.
Lines 29-34 define the binary message that corresponds to token value 30.
Line 36 is the start of the program.
Lines 38-47 declare necessary local variables.
Lines 50-54 check that the number of command line variables is correct.
Line 57 isolates the message type from the command line.
Lines 60-91 build the outgoing message based on the passed in message type.
Lines 94-98 attach the simpl name.
Lines 101-106 name locate the receiving program.
Lines 109-114 send the message to the receiving program.

Let's examine the receiving program.

      1 """
      2 receiver_gui3.py: This is a python simpl gui-based receiver.
      3 Refer to lesson #5.
      4 Usage: python3 receiver_gui3.py
      5 """
      6 
      7 
      8 # import necessary modules
      9 import sys
     10 from tkinter import *
     11 from tkinter.scrolledtext import *
     12 import csimpl
     13 
     14 # define functionality to be performed whan a message is received
     15 def hndlMessage(a, b):
     16         # receive a message
     17         messageSize, senderId = nee.receive()
     18 
     19         # check for error
     20         if messageSize == -1:
     21                 print ("%s: receive error-%s" %(rName, nee.whatsMyError()))
     22                 sys.exit(-1)
     23         # is it a non-null message?
     24         elif messageSize > 0:
     25                 # extract the token from the message
     26                 token = nee.unpackMsg(nee.BIN, "i")
     27                 # react to the token
     28                 tokenAction(token)
     29 
     30         # reply to the sender
     31         retVal = nee.reply(senderId)
     32         if retVal == -1:
     33                 print ("%s: reply error-%s" %(rName, nee.whatsMyError()))
     34                 sys.exit(-1)
     35 ction(token):
     37         if token == 10:
     38                 var1,var2,var3=nee.unpackMsg(nee.BIN,"iii")
     39                 var = "\ntoken=%d var1=%d var2=%d var3=%d" %(token, var1, var2, var3)
     40                 text.insert(END, var)
     41         elif token == 20:
     42                 var1=nee.unpackMsg(nee.BIN,"f")
     43                 var = "\ntoken=%d var1=%f" %(token, var1)
     44                 text.insert(END, var)
     45         elif token == 30:
     46                 length,var1=nee.unpackMsg(nee.BIN,"i32s")
     47                 var = "\ntoken=%d var1=%s" %(token, var1)
     48                 text.insert(END, var)
     49         else:
     50                 print ("\n%s: unknown token type=%d" %(rName, token))
     51 
     52 # define callback function when exit button is selected
     53 def finish(event):
     54         sys.exit(0)
     55 
     56 # set this program's name
     57 rName = "RECEIVER"
     58 
     59 nee=csimpl.Simpl(rName, 1024)
     60 if (nee == -1):
     61         print ("%s: name attach error-%s" %(rName, wcsimpl.whatsMyError()))
     62         sys.exit(-1)
     63 
     64 # initialize Tk for graphics
     65 root = Tk()
     66 
     67 # get the receive fifo file descriptor
     68 fd = nee.whatsMyReceiveFd()
     69 
     70 # attach a callback for incoming simpl messages
     71 root.tk.createfilehandler(fd, READABLE, hndlMessage)
     72 
     73 # build an exit button widget
     74 button = Button(root)
     75 button["text"] = "Exit"
     76 button.bind("<Button>",finish)
     77 button.pack()
     78 
     79 # build a scrolled list for displaying incoming messages
     80 text = ScrolledText(root, background="white")
     81 text.pack()
     82 
     83 # handle user input and simpl messaging
     84 root.mainloop()

Lines 9-12 import the necessary modules for simpl, graphics and so on.
Lines 14-34 define the callback function for the event which signals that a simpl message has been received. The message is received, the token is extracted, the message is then parsed and displayed in a scrolling list based on the value of the token. Finally, the sender is unblocked by replying a null message.
Lines 36-50 define the function that does the actual unpacking of the incoming message as well as loading the scrolling list widget with the message contents.
Lines 56-62 set the script's name and performs the simpl name attach.
Line 65 initializes Tkinter and loads the root variable with the required information for the root window.
Line 68 is very important. This simpl call provides the unique file descriptor that is used internally by simpl for the receive fifo.
Line 71 is extremely important. This call allows a sort of select() methodology on the event loop that is contained in root.mainloop() (line 84). This is the vehicle for notifying Python that it must also baby-sit the file descriptor where the simpl message action takes place as well as looking after the usual gui input.
Lines 73-77 build the exit button widget.
Lines 79-81 build the scrolling test widget used for displaying message information.build the exit button widget.
Line 84 is the infinite gui event loop.

The Makefile for the C sender program.

The sender program must be compiled and linked before it can be of any use. Go to ../src and at the command prompt type:

make clean
Then type:
make install
This makes a new executable of sender.c called sender and puts it in ../bin .
 
 

Note:

In order to run this Makefile, the shell variable SIMPL_HOME must be set so that the make can find the simpl header and library.

 
 

Let's run the two programs.

In order to run the receiver_gui.py script and the C sender program, do the following:

  1. make sure that PYTHONPATH has been exported to your shell.
    ie. export PYTHONPATH=$(SIMPL_HOME)/python/modules
  2. open a shell window. This can be opened from a desktop such as KDE or GNOME.
  3. in this shell window,  change directory to src.
  4. start the python receiver program. That is at the command line prompt type:  python3 receiver_gui3.py
  5. open another shell window next to the first one.
  6. change directory to bin.
  7. this time, run the sender program. That is,  at the command prompt type: sender 10


The command indicates:

  1. the program to run is sender,
  2. the name of the receiver program is RECEIVER, and
  3. the message type to send is indicated by token = 10.


You should see the receiver program report the contents of each message in a scrollable list as you send the various messages via the sender program.
Try sending the other messages for which token = 20 and 30.
 
 

Summary

Let's summarize what you should have observed in this lesson:

End of Lesson 5.


Copyright of iCanProgram Inc.  2012