![]() |
Welcome to SIMPL Programming for Python
|
| 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 cleanThen type:
make installThis 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:
The command indicates:
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: