/* Handles the response to QUERY_MSG messages */ static void replyHandler (MSG_INSTANCE msgRef, BYTE_ARRAY callData, void *clientData) { printf("replyHandler: Receiving message %s (%s) [%s]\n", IPC_msgInstanceName(msgRef), (char *)callData, (char *)clientData); IPC_freeByteArray(callData); }
///handler needed for odom message and velocity message void qc_imu_imu_message_handler(MSG_INSTANCE mi, BYTE_ARRAY callData, void* clientData){ (void) clientData; //no warning IPC_RETURN_TYPE err = IPC_OK; err = IPC_unmarshallData(IPC_msgInstanceFormatter(mi), callData, &imsg, sizeof(imsg)); newImuMessageAvailable = true; IPC_freeByteArray(callData); IPC_freeDataElements(IPC_msgInstanceFormatter(mi),&imsg); }
/* Message handler function - It gets called when we receive a message * with the name "ListeningToAndroid" */ static void msgHandler(MSG_INSTANCE msgRef, BYTE_ARRAY callData, void *clientData) { drive_arc_command_msg_type msg1; double radius, time, speed; char sender[20]; time_type timestamp; IPC_unmarshallData(IPC_msgInstanceFormatter(msgRef), callData, &msg1, sizeof(msg1)); fp=fopen("CommandLog.txt","a"); fprintf(fp,"Command Radius: %f, Speed: %f, Time: %f",msg1.radius,msg1.speed,msg1.time); fprintf(fp,"\tSender: %s",msg1.sender.data); time_t commandTime=msg1.timestamp.tv_sec; fprintf(fp,"\tTimestamp: %s", ctime(&commandTime)); fclose(fp); sendZoeResponse(msg1); IPC_freeByteArray(callData); }
static void MsgHnd (MSG_INSTANCE msgRef, void *data, void *ClientData) { #ifdef UNUSED_PRAGMA #pragma unused(msgRef, ClientData) #endif static double sum = 0.0; static double sumSq = 0.0; static double max = 0.0; static double min = 1.0e10; static int msgCount = 0; static struct timeval firstTime; struct timeval now, before; double diff, ave; //#define SENDING_INTS #ifdef SENDING_INTS // If sender using 32 bit machine struct timeval_int {int sec, usec; }; struct timeval_int *before1; #endif gettimeofday(&now, NULL); msgCount++; #ifdef SENDING_INTS before1 = (struct timeval_int *)data; before.tv_sec = before1->sec; before.tv_usec = before1->usec; #else before = *(struct timeval *)data; #endif diff = 1000*sslCalcTimevalDiff(&now, &before); sum += diff; sumSq += diff*diff; if (diff > max) max = diff; if (diff < min) min = diff; if (msgCount == 1) { firstTime = now; } else if (msgCount == NSEND) { ave = sum/msgCount; diff = sslCalcTimevalDiff(&now, &firstTime); printf("Latency for %d messages: Max: %.2f msecs, Min: %.2f, Mean: %.2f (%.2f), Std Dev: %.2f\n", msgCount, max, min, ave, 1000*(diff/msgCount), sqrt(sumSq/msgCount - (ave*ave))); msgCount = 0; max = sum = sumSq = 0.0; min = 1.0e10; } IPC_freeByteArray(data); }
/* Unmarshall the byte array and print it out. */ static void msg3Handler (MSG_INSTANCE msgRef, BYTE_ARRAY callData, void *clientData) { #ifdef UNUSED_PRAGMA #pragma unused(clientData) #endif FORMATTER_PTR formatter; void *dataptr; printf("msg3Handler: Receiving message %s: ", IPC_msgInstanceName(msgRef)); /* Get the formatter for this message instance */ formatter = IPC_msgInstanceFormatter(msgRef); IPC_unmarshall(formatter, callData, &dataptr); IPC_printData(formatter, stdout, dataptr); /* Free up malloc'd data */ IPC_freeByteArray(callData); IPC_freeData(formatter, dataptr); }
static void msgHandler (MSG_INSTANCE msgRef, BYTE_ARRAY callData, void *clientData) { FORMATTER_PTR formatter; carmen_test_ipc_message msg; formatter = IPC_msgInstanceFormatter(msgRef); IPC_unmarshallData(formatter, callData, &msg, sizeof(carmen_test_ipc_message)); IPC_freeByteArray(callData); #if (defined(__x86_64__)) fprintf(stderr, "Got message from client %ld : time %f\n", (long)clientData, msg.timestamp); #else fprintf(stderr, "Got message from client %d : time %f\n", (int)clientData, msg.timestamp); #endif }
static void queryHandler (MSG_INSTANCE msgRef, BYTE_ARRAY callData, void *clientData) { char *publishStr = "Published"; char *responseStr = "Responded"; printf("queryHandler: Receiving message %s of %d bytes (%s) [%s]\n", IPC_msgInstanceName(msgRef), IPC_dataLength(msgRef), (char *)callData, (char *)clientData); /* Publish this message -- all subscribers get it */ printf("\n IPC_publish(%s, %d, %s)\n", MSG2, (int)strlen(publishStr)+1, publishStr); IPC_publish(MSG2, strlen(publishStr)+1, publishStr); /* Respond with this message -- only the query handler gets it */ printf("\n IPC_respond(msgRef, %s, %d, %s)\n", MSG2, (int)strlen(responseStr)+1, responseStr); IPC_respond(msgRef, MSG2, strlen(responseStr)+1, responseStr); IPC_freeByteArray(callData); }
int main (int argc, char **argv) #endif { #ifndef VXWORKS int numTrials; char *formatString; #endif int i; FORMATTER_PTR format; char data[MAX_DATA_SIZE]; /* No error checking if the format is too big */ void *dataPtr; IPC_VARCONTENT_TYPE vc; bzero(data, MAX_DATA_SIZE); #ifndef VXWORKS if (argc == 1) { fprintf(stderr, "Usage %s: <format_string> [num_trials]\n", argv[0]); exit(-1); } formatString = argv[1]; numTrials = (argc > 2 ? atoi(argv[2]) : DEFAULT_TRIALS); #endif IPC_initialize(); format = IPC_parseFormat(formatString); if (!format) { fprintf(stderr, "Illegal format string: %s\n", formatString); exit(-1); } /* Marshall tests */ printf("Marshalling trial with %s\n", formatString); printf(" Struct Size: %d, Buffer Size: %d (%s size)\n", x_ipc_dataStructureSize(format), (formatContainsPointers(format) ? -1 : x_ipc_bufferSize(format, NULL)), (x_ipc_sameFixedSizeDataBuffer(format) ? "fixed" : "variable")); TIME_TRIAL({ IPC_marshall(format, &data, &vc); IPC_freeByteArray(vc.content);})
JNIEXPORT void JNICALL Java_ipc_java_IPC_IPC_1freeByteArray (JNIEnv *env, jclass theClass, jlong byteArray) { IPC_freeByteArray((BYTE_ARRAY)(size_t)byteArray); }
void qc_odometry_odometry_message_handler(MSG_INSTANCE mi, BYTE_ARRAY callData, void* clientData){ (void) clientData; //no warning IPC_RETURN_TYPE err = IPC_OK; prev_omsg = omsg; err = IPC_unmarshallData(IPC_msgInstanceFormatter(mi), callData, &omsg, sizeof(omsg)); if (newImuMessageAvailable){ newImuMessageAvailable = false; prev_vmsg = vmsg; vmsg.timestamp_sec = omsg.timestamp_sec; vmsg.timestamp_usec = omsg.timestamp_usec; if (msgcounter > 2) validData = true; if (validData){ double dtv = omsg.timestamp_sec - prev_omsg.timestamp_sec + 1e-6 * (omsg.timestamp_usec - prev_omsg.timestamp_usec); double dta = vmsg.timestamp_sec - prev_vmsg.timestamp_sec + 1e-6 * (vmsg.timestamp_usec - prev_vmsg.timestamp_usec); vmsg.x = omsg.x; vmsg.y = omsg.y; vmsg.z = omsg.z; vmsg.q0 = omsg.q0; vmsg.q1 = omsg.q1; vmsg.q2 = omsg.q2; vmsg.q3 = omsg.q3; vmsg.roll = omsg.roll; vmsg.pitch = omsg.pitch; vmsg.yaw = omsg.yaw; Transformation3<double> delta; Transformation3<double> p0(DVector3(prev_omsg.x, prev_omsg.y, prev_omsg.z), Quaternion<double>(prev_omsg.q0, prev_omsg.q1, prev_omsg.q2, prev_omsg.q3)); Transformation3<double> p1(DVector3(omsg.x, omsg.y, omsg.z), Quaternion<double>(omsg.q0, omsg.q1, omsg.q2, omsg.q3)); delta = p0.inv() * p1; ///velocity && acceleration based on omsg if (dtv > 1e-7){ dtv = 1./dtv; vmsg.vx = delta.translationVector.x() * dtv; vmsg.vy = delta.translationVector.y() * dtv; vmsg.vz = delta.translationVector.z() * dtv; if (dta > 1e-7){ ///take into account the different orientations of the velocities! p0.translationVector = DVector3(0,0,0); p0.rotationQuaternion = Quaternion<double>(prev_vmsg.q0, prev_vmsg.q1, prev_vmsg.q2, prev_vmsg.q3); p0.translationVector = p0 * DVector3(prev_vmsg.vx, prev_vmsg.vy, prev_vmsg.vz); p1.translationVector = DVector3(0,0,0); p1.rotationQuaternion = Quaternion<double>(vmsg.q0, vmsg.q1, vmsg.q2, vmsg.q3); p1.translationVector = p1 * DVector3(vmsg.vx, vmsg.vy, vmsg.vz); delta = p0.inv() * p1; dta = 1./dta; vmsg.avx = delta.translationVector.x() * dta; vmsg.avy = delta.translationVector.y() * dta; vmsg.avz = delta.translationVector.z() * dta; } else { vmsg.avx = vmsg.avy = vmsg.avz = 0; } } else { vmsg.avx = vmsg.avy = vmsg.avz = 0; vmsg.vx = vmsg.vy = vmsg.vz = 0; } ///acceleration based on imu data ///FIXME ///acceleration based on tan roll and tan pitch Quaternion<double> q(imsg.q0, imsg.q1, imsg.q2, imsg.q3); DVector3 an = q.toAngles(); vmsg.axtanp = tan(an.pitch()) * 9.81; vmsg.aytanr = tan(an.roll()) * 9.81; qc_odometry_publish_velocity_message(&vmsg); } } IPC_freeByteArray(callData); IPC_freeDataElements(IPC_msgInstanceFormatter(mi),&omsg); msgcounter++; if (!(msgcounter%10)) std::cerr << "." << std::flush; }
void ipcTest1(void) { /* Actually send one more byte (end-of-string) */ #define FIVE_BYTE_MSG_LEN 6 #define SIX_BYTE_MSG_LEN 7 #define EIGHT_BYTE_MSG_LEN 9 char fiveBytes[FIVE_BYTE_MSG_LEN] = "abcde"; char sixBytes[SIX_BYTE_MSG_LEN] = "abcdef"; char eightBytes[EIGHT_BYTE_MSG_LEN] = "abcdefgh"; fiveBytes[FIVE_BYTE_MSG_LEN-1] = '\0'; sixBytes[SIX_BYTE_MSG_LEN-1] = '\0'; eightBytes[EIGHT_BYTE_MSG_LEN-1] = '\0'; /**************************************************************** * TESTS OF THE BASIC IPC INTERFACE ****************************************************************/ /* Connect to the central server */ printf("\nIPC_connect(%s)\n", TASK_NAME); IPC_connect(TASK_NAME); /* Default is to exit on error; Override default, because some of the tests in this file explicitly induce errors. */ printf("\nIPC_setVerbosity(IPC_Print_Errors)\n"); IPC_setVerbosity(IPC_Print_Errors); /* Test out the timers */ realStart = x_ipc_timeInMsecs(); printf("\nIPC_addTimer(1000, TRIGGER_FOREVER, timerHandler, \"timer1\")\n"); IPC_addTimer(1000, TRIGGER_FOREVER, (TIMER_HANDLER_TYPE)timerHandler, (void *)"timer1"); /* Define a fixed length message (no format string) */ printf("\nIPC_defineMsg(%s, %d, NULL)\n", MSG1, FIVE_BYTE_MSG_LEN); IPC_defineMsg(MSG1, FIVE_BYTE_MSG_LEN, NULL); /* Define a variable length message (no format string) */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, NULL)\n", MSG2); IPC_defineMsg(MSG2, IPC_VARIABLE_LENGTH, NULL); printf("\nIPC_isMsgDefined(%s) => %s\n", MSG1, IPC_isMsgDefined(MSG1) ? "TRUE" : "FALSE"); printf("\nIPC_isMsgDefined(%s) => %s\n", MSG3, IPC_isMsgDefined(MSG3) ? "TRUE" : "FALSE"); /* Subscribe to the first message, with client data */ printf("\nIPC_subscribe(%s, msg1Handler, %s)\n", MSG1, "client1a"); IPC_subscribe(MSG1, msg1Handler, (void *)"client1a"); /* Subscribe to the second message, with client data */ printf("\nIPC_subscribe(%s, msg1Handler, %s)\n", MSG2, "client2a"); IPC_subscribe(MSG2, msg1Handler, (void *)"client2a"); /* Publish the fixed length message and listen for it (in this simple example program, both publisher and subscriber are in the same process */ printf("\nIPC_publish(%s, IPC_FIXED_LENGTH, %s)\n", MSG1, fiveBytes); if (IPC_publish(MSG1, IPC_FIXED_LENGTH, fiveBytes) == IPC_OK) /* MSECS is a simple macro that converts from seconds to msecs */ IPC_listenClear(MSECS(1)); /* Publish the fixed length message, giving the length explicitly */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_publish(%s, %d, %s)\n", MSG1, FIVE_BYTE_MSG_LEN, fiveBytes); if (IPC_publish(MSG1, FIVE_BYTE_MSG_LEN, fiveBytes) == IPC_OK) IPC_listenClear(MSECS(1)); /* Produces an error, since the length passed is not the defined length */ printf("\nIPC_publish(%s, %d, %s)\n", MSG1, 10, fiveBytes); if (IPC_publish(MSG1, 10, fiveBytes) == IPC_Error) printf("ERROR\n"); /* Publish the variable length message, sending (and receiving) 5 bytes */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_publish(%s, %d, %s)\n", MSG2, FIVE_BYTE_MSG_LEN, fiveBytes); if (IPC_publish(MSG2, FIVE_BYTE_MSG_LEN, fiveBytes) == IPC_OK) IPC_listenClear(MSECS(1)); /* Publish the same variable length message, this time sending 8 bytes */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_publish(%s, %d, %s)\n", MSG2, EIGHT_BYTE_MSG_LEN, eightBytes); if (IPC_publish(MSG2, EIGHT_BYTE_MSG_LEN, eightBytes) == IPC_OK) IPC_listenClear(MSECS(1)); /* Produces an error: Cannot pass IPC_VARIABLE_LENGTH as an argument */ printf("\nIPC_publish(%s, IPC_VARIABLE_LENGTH, %s)\n", MSG2, eightBytes); if (IPC_publish(MSG2, IPC_VARIABLE_LENGTH, eightBytes) == IPC_Error) printf("ERROR\n"); /* Produces an error: "msg2" is a variable length message */ printf("\nIPC_publish(%s, IPC_FIXED_LENGTH, %s)\n", MSG2, eightBytes); if (IPC_publish(MSG2, IPC_FIXED_LENGTH, eightBytes) == IPC_Error) printf("ERROR\n"); /* Get notified when handlers subscribe/unsubscribe to "msg2" */ printf("\n%d handlers currently subscribed to " MSG2, IPC_numHandlers(MSG2)); printf("\nIPC_subscribeHandlerChange("MSG2", handlerChangeHandler, NULL)\n"); IPC_subscribeHandlerChange(MSG2, handlerChangeHandler, NULL); /* Subscribe a second message handler for "msg2" */ printf("\nIPC_subscribe(%s, msg2Handler, %s)\n", MSG2, "client2b"); IPC_subscribe(MSG2, msg2Handler, (void *)"client2b"); /* If doing direct broadcasts, need to listen to get the direct info update */ IPC_listen(250); /* Publish the message -- receive two messages (one for msg1Handler, one for msg2Handler). */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_publish(%s, %d, %s)\n", MSG2, EIGHT_BYTE_MSG_LEN, eightBytes); if (IPC_publish(MSG2, EIGHT_BYTE_MSG_LEN, eightBytes) == IPC_OK) { /* Make sure all the subscribers get invoked before continuing on (keep listening until a second has passed without any msgs) */ while (IPC_listen(MSECS(1)) != IPC_Timeout){}; } /* Remove this subscription */ printf("\nIPC_unsubscribe(%s, msg2Handler)\n", MSG2); IPC_unsubscribe(MSG2, msg2Handler); /* If doing direct broadcasts, need to listen to get the direct info update */ IPC_listen(250); /* No longer get notified when handlers are added/removed */ printf("\nIPC_unsubscribeHandlerChange("MSG2", handlerChangeHandler)\n"); IPC_unsubscribeHandlerChange(MSG2, handlerChangeHandler); printf(" IPC_subscribe(%s, msg2Handler, %s)\n", MSG2, "client2c"); IPC_subscribe(MSG2, msg2Handler, (void *)"client2c"); printf(" IPC_unsubscribe(%s, msg2Handler)\n", MSG2); IPC_unsubscribe(MSG2, msg2Handler); /* Publish the message -- receive one message (for msg1Handler) */ printf("\nIPC_publish(%s, %d, %s)\n", MSG2, EIGHT_BYTE_MSG_LEN, eightBytes); if (IPC_publish(MSG2, EIGHT_BYTE_MSG_LEN, eightBytes) == IPC_OK) IPC_listenClear(MSECS(1)); /* Subscription of the same message handler *replaces* the old client data */ printf("\nIPC_subscribe(%s, msg1Handler, %s)\n", MSG1, "client1b"); IPC_subscribe(MSG1, msg1Handler, (void *)"client1b"); /* Receive one message (for msg1Handler), but now with new client data. Note use of IPC_publishFixed. */ printf("\nIPC_publishFixed(%s, %s)\n", MSG1, fiveBytes); if (IPC_publishFixed(MSG1, fiveBytes) == IPC_OK) IPC_listenClear(MSECS(1)); /* Remove subscription to "msg1" */ printf("\nIPC_unsubscribe(%s, msg1Handler)\n", MSG1); IPC_unsubscribe(MSG1, msg1Handler); /* If doing direct broadcasts, need to listen to get the direct info update */ IPC_listen(250); /* Receive no messages -- IPC_listenClear times out */ printf("\nIPC_publishFixed(%s, %s)\n", MSG1, fiveBytes); if (IPC_publishFixed(MSG1, fiveBytes) == IPC_OK) if (IPC_listen(MSECS(1)) == IPC_Timeout) printf("Timed out\n"); /**************************************************************** * TESTS OF THE QUERY/RESPONSE FUNCTIONS ****************************************************************/ /* The handler of QUERY_MSG does two things: It *publishes* a message of type MSG2, and it *responds* to the query with a message of type MSG2. The published message gets handled only by the subscriber (msg1Handler), and the response gets handled only be replyHandler, since a response is a directed message. */ /* NOTE: It is perfectly OK to subscribe to a message before it is defined! */ printf("\nIPC_subscribe(%s, queryHandler, %s)\n", QUERY_MSG, "qtest"); IPC_subscribe(QUERY_MSG, queryHandler, (void *)"qtest"); printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, NULL)\n", QUERY_MSG); IPC_defineMsg(QUERY_MSG, IPC_VARIABLE_LENGTH, NULL); /* This call allows IPC to send the process 2 messages at a time, rather than queueing them in the central server. This is needed in this example program because the sender and receiver of the query are the same process. If this is taken out, the only difference is that the message that is published in queryHandler arrives *after* the message responded to (even though it is sent first). This function should not be needed when we switch to using point-to-point communications (rather than sending via the central server). */ IPC_setCapacity(2); /* Send one extra byte -- for end-of-string */ printf("\nIPC_queryNotify(%s, %d, %s, replyHandler, %s)\n", QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes, "Notification"); IPC_queryNotify(QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes, replyHandler, (void *)"Notification"); /* Make sure all the messages spawned by this query get handled before continuing (keep listening until a second has passed without any msgs) */ while (IPC_listen(MSECS(1)) != IPC_Timeout){}; { char *replyHandle = NULL; /* This essentially does the same thing as IPC_queryNotify above, except it is blocking, and sets the replyHandle to be the data responded to. Don't need to listen, since that is done within queryResponse, but could be dangerous to wait forever (if the response never comes ...) */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_queryResponse(%s, %d, %s, replyHandle, IPC_WAIT_FOREVER)\n", QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes); if (IPC_queryResponse(QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes, (void **)(void *)&replyHandle, IPC_WAIT_FOREVER) == IPC_OK) { printf("Blocking Response: %s\n", replyHandle); IPC_freeByteArray((void *)replyHandle); } /* This one should time out before the response arrives */ /* Send one extra byte -- for end-of-string */ printf("\nIPC_queryResponse(%s, %d, %s, replyHandle, %d)\n", QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes, 0); if (IPC_queryResponse(QUERY_MSG, SIX_BYTE_MSG_LEN, sixBytes, (void **)(void *)&replyHandle, 0) == IPC_OK) { printf("Blocking Response: %s\n", replyHandle); IPC_freeByteArray((void *)replyHandle); } else { /* NOTE: Since the function call times out before handling messages, * (a) The *response* to the query is lost (for good) * (b) The message *published* in queryHandler is waiting for the next * time the module listens for messages (which actually occurs * in IPC_msgFormatter, below). */ printf("queryResponse timed out (replyHandle: %ld)\n", (long)replyHandle); } } /**************************************************************** * TESTS OF THE MARSHALLING FUNCTIONS ****************************************************************/ /* Test the marshalling/unmarshalling functions, independently of * sending/receiving messages */ { IPC_VARCONTENT_TYPE varcontent; SAMPLE_TYPE sample; SAMPLE_PTR sample2Ptr; sample.i1 = 666; sample.str1 = "hello, world"; sample.d1 = 3.14159; printf("\nIPC_marshall(...)\n"); IPC_marshall(IPC_parseFormat(SAMPLE_FORMAT), &sample, &varcontent); printf("Marshall of 'sample' [length: %d]\n", varcontent.length); printf("\nIPC_unmarshall(...)\n"); IPC_unmarshall(IPC_parseFormat(SAMPLE_FORMAT), varcontent.content, (void **)(void *)&sample2Ptr); printf("Orig: <%d, %s, %f>\nCopy: <%d, %s, %f>\n", sample.i1, sample.str1, sample.d1, sample2Ptr->i1, sample2Ptr->str1, sample2Ptr->d1); IPC_freeByteArray(varcontent.content); IPC_freeData(IPC_parseFormat(SAMPLE_FORMAT), sample2Ptr); } { IPC_VARCONTENT_TYPE varcontent; MATRIX_LIST_TYPE m1, m2, m3; int i, j, k; char *string; /* Define a variable-length message whose format is simply an integer */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, %s)\n", MSG3, INT_FORMAT); IPC_defineMsg(MSG3, IPC_VARIABLE_LENGTH, INT_FORMAT); /* Define a variable-length message whose format is a string */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, %s)\n", MSG4, STRING_FORMAT); IPC_defineMsg(MSG4, IPC_VARIABLE_LENGTH, STRING_FORMAT); /* Define a variable-length message whose format is a complex structure */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, %s)\n", MSG5, MATRIX_LIST_FORMAT); IPC_defineMsg(MSG5, IPC_VARIABLE_LENGTH, MATRIX_LIST_FORMAT); /* Subscribe to each of the above messages, all using the same handler */ printf("\nIPC_subscribe(%s, msg3Handler, NULL)\n", MSG3); IPC_subscribe(MSG3, msg3Handler, NULL); printf("\nIPC_subscribe(%s, msg3Handler, NULL)\n", MSG4); IPC_subscribe(MSG4, msg3Handler, NULL); printf("\nIPC_subscribe(%s, msg3Handler, NULL)\n", MSG5); IPC_subscribe(MSG5, msg3Handler, NULL); /* Marshall the integer into a byte array (takes byte-order into account) */ i = 42; printf("\nIPC_marshall(...)\n"); IPC_marshall(IPC_msgFormatter(MSG3), &i, &varcontent); /* Publish the marshalled byte array (message handler prints the data) */ printf("\nIPC_publishVC(%s, varcontent[%d])\n", MSG3, varcontent.length); IPC_publishVC(MSG3, &varcontent); IPC_freeByteArray(varcontent.content); IPC_listenClear(MSECS(1)); /* Marshall the string into a byte array. NOTE: Need to pass a *pointer* to the string! */ string = "Hello, world"; /* It's much better (safer) to use IPC_msgFormatter, but this is included just to illustrate the use of IPC_parseFormat */ printf("\nIPC_marshall(...)\n"); IPC_marshall(IPC_parseFormat(STRING_FORMAT), &string, &varcontent); /* Publish the marshalled byte array (message handler prints the data) */ printf("\nIPC_publishVC(%s, varcontent[%d])\n", MSG4, varcontent.length); IPC_publishVC(MSG4, &varcontent); IPC_freeByteArray(varcontent.content); IPC_listenClear(MSECS(1)); /* Set up a sample MATRIX_LIST structure */ for (k=0, i=0; i<2; i++) for (j=0; j<2; j++) m1.matrix[i][j] = (i+j+k); m1.matrixName = "TheFirst"; m1.count = k; m1.next = &m2; for (k++, i=0; i<2; i++) for (j=0; j<2; j++) m2.matrix[i][j] = (i+j+k); m2.matrixName = "TheSecond"; m2.count = k; m2.next = &m3; for (k++, i=0; i<2; i++) for (j=0; j<2; j++) m3.matrix[i][j] = (i+j+k); m3.matrixName = "TheThird"; m3.count = k; m3.next = NULL; /* IPC_publishData both marsalls and publishes the data structure */ printf("\nIPC_publishData(%s, m1)\n", MSG5); IPC_publishData(MSG5, &m1); IPC_listenClear(MSECS(1)); } /* Use of IPC_queryResponseData and IPC_respondData -- Send out a message with a matrix_list format; The response is a message with the first matrix, but each element incremented by one. */ { MATRIX_LIST_TYPE m1; MATRIX_TYPE *matrixPtr; int i, j, k; /* Define the "query" message */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, %s)\n", QUERY2_MSG, MATRIX_LIST_FORMAT); IPC_defineMsg(QUERY2_MSG, IPC_VARIABLE_LENGTH, MATRIX_LIST_FORMAT); /* Define the "response" message */ printf("\nIPC_defineMsg(%s, IPC_VARIABLE_LENGTH, %s)\n", RESPONSE2_MSG, MATRIX_FORMAT); IPC_defineMsg(RESPONSE2_MSG, IPC_VARIABLE_LENGTH, MATRIX_FORMAT); /* Subscribe to query message with automatic unmarshalling */ printf("\nIPC_subscribeData(%s, query2Handler, NULL)\n", QUERY2_MSG); IPC_subscribeData(QUERY2_MSG, query2Handler, NULL); /* Set up a sample MATRIX_LIST structure */ for (k=0, i=0; i<2; i++) for (j=0; j<2; j++) m1.matrix[i][j] = (i+j+k); m1.matrixName = "TheFirst"; m1.count = k; m1.next = NULL; /* IPC_queryResponseData both marsalls and sends the data structure */ printf("\nIPC_queryResponseData(%s, m1, matrixPtr, IPC_WAIT_FOREVER)\n", QUERY2_MSG); if (IPC_queryResponseData(QUERY2_MSG, (void *)&m1, (void **)(void *)&matrixPtr, IPC_WAIT_FOREVER) == IPC_OK) { IPC_printData(IPC_msgFormatter(RESPONSE2_MSG), stdout, matrixPtr); } else { printf("IPC_queryResponseData failed\n"); } } #if !defined(VXWORKS) && !defined(_WINSOCK_) /* Don't do this for vxworks, since it does not handle stdin from the terminal, nor for winsock, since it does not seem to be able to use select on a non-socket fd */ /* Subscribe a handler for tty input. Now, typing at the terminal will echo the input. Typing "q" will quit the program; typing "m" will send a message; typing "u" will unsubscribe the handler (the program will no longer listen to input). */ printf("\nIPC_subscribeFD(%d, stdinHnd, %s)\n", fileno(stdin), "FD1"); IPC_subscribeFD(fileno(stdin), stdinHnd, (void *)"FD1"); printf("\nEntering dispatch loop (terminal input is echoed, type 'q' to quit,\n"); printf(" 'm' to send a message, 'u' to stop listening to stdin).\n"); IPC_dispatch(); #endif /* If ever reaches here, shut down gracefully */ IPC_disconnect(); }