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

Lines 10-13 import the necessary modules for simpl, graphics and so on.
Lines 16-35 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 37-54 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 61-67 set the script's name and performs the simpl name attach.
Line 70 is very important. This simpl call provides the unique file descriptor that is used internally by simpl for the receive fifo.
Line 73 initializes Tkinter and loads the root variable with the required information for the root window.
Line 76 is extremely important. This call allows a sort of select() methodology on the event loop that is contained in root.mainloop() (line 89). 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 79-83 build the exit button widget.
Lines 85-86 build the scrolling test widget used for displaying message information.build the exit button widget.
Line 89 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:  python receiver_gui.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 py_receiver 10


The command indicates:

  1. the program to run is sender,
  2. the name of the receiver program is py_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.  2003