This is MathConnector.m in view mode; [Download] [Up]
// MathConnector.m // By Charles G. Fleming, Educational Computing Services, Allegheny College. // Copyright 1993, Allegheny College. // You may freely copy, distribute and reuse this code. // Allegheny College and the author disclaim any warranty of any kind, // expressed or implied, as to its fitness for any particular use. #import "MathConnector.h" #import <objc/NXBundle.h> #import <strings.h> #import <stdlib.h> #include <stdio.h> @implementation MathConnector int readPacket(MLINK); void readAndPrintExpression(MLINK); void error(MLINK); // Make sure linkPointer is initialized and then start up Mathematica. - init { id returnVal; self = [super init]; linkPointer = NULL; // If we can't form a MathLink connection to Mathematica, we return // nil. if([self initMathConnection]) returnVal = self; else { NXRunAlertPanel("Error", "Unable to form a MathLink connection " "with Mathematica.", NULL, NULL, NULL); returnVal = nil; } return returnVal; } // Open a MathLink connection to Mathematica. - (MLINK)initMathConnection { int numArgs = 2; char *args[] = {"-linkname", "math -mathlink", NULL}; // Open a MathLink connection. linkPointer = MLOpen(numArgs, args); // Take care of the initial messages sent by Mathematica. if(linkPointer != NULL) { // Mathematica sends a text packet containing the string // " -- NeXT graphics initialized -- ". MLNextPacket(linkPointer); MLNewPacket(linkPointer); // Mathematica then sends a text packet containing // the string "\n" MLNextPacket(linkPointer); MLNewPacket(linkPointer); // Mathematica then sends an input name packet containing the // string // " In[1]:= " MLNextPacket(linkPointer); MLNewPacket(linkPointer); } if(MLError(linkPointer)) linkPointer = NULL; return linkPointer; } // Return the linkPointer if a connection was formed or NULL. - (MLINK)link { return linkPointer; } // Send "non-matrix" commands to Mathematica. - (BOOL)evaluateExpression:(char *)string resultType:(int)type result:(void**)result { char *commandString, *resultString, *returnedString; BOOL success = YES; int returnedInt, *nonVolatileInt, packetTag, packetType; double returnedDouble, *nonVolatileDouble; commandString = malloc(strlen(string) + 50); switch(type) { case STRING: sprintf(commandString, "ToString[%s, PageWidth->70]", string); break; case DEFINITION: sprintf(commandString, "ToString[%s, PageWidth->70]", string); break; case GRAPHICS: sprintf(commandString, "ToString[%s]", string); break; case INTEGER: strcpy(commandString, string); break; case REAL: strcpy(commandString, string); break; default: success = NO; break; } // If an illegal type was specified, we'll return NO. if(!success) { free(commandString); return NO; } // Ship the command off to Mathematica. MLReturnValue = MLPutFunction(linkPointer, "ToExpression", 1); MLPutString(linkPointer, commandString); MLEndPacket(linkPointer); free(commandString); //readPacket(linkPointer); //return NO; // Get the result of the execution of the command. packetType = MLNextPacket(linkPointer); switch(packetType) { case RETURNPKT: if(type == DEFINITION) { // Throw away anything returned. MLNewPacket(linkPointer); resultString = (char *)malloc(2); strcpy(resultString, ""); *result = resultString; return YES; } packetTag = MLGetNext(linkPointer); switch(packetTag) { case MLTKSTR: if(MLGetString(linkPointer, &returnedString)) { resultString = (char *)malloc(strlen(returnedString) +1); strcpy(resultString, returnedString); *result = resultString; MLDisownString(linkPointer, returnedString); } else success = NO; break; case MLTKINT: if(MLGetInteger(linkPointer, &returnedInt)) { nonVolatileInt = (int *)malloc(sizeof(int)); memcpy(nonVolatileInt, &returnedInt, sizeof(int)); *result = nonVolatileInt; } else success = NO; break; case MLTKREAL: if(MLGetDouble(linkPointer, &returnedDouble)) { nonVolatileDouble = (double *)malloc(sizeof(double)); memcpy(nonVolatileDouble, &returnedDouble, sizeof(double)); *result = nonVolatileDouble; } else success = NO; break; case MLTKSYM: case MLTKFUNC: // Discard the packet. MLNewPacket(linkPointer); success = NO; break; case MLTKERROR: default: MLNewPacket(linkPointer); if(MLError(linkPointer)) MLClearError(linkPointer); success = NO; break; } break; case MESSAGEPKT: // Discard the MLTKSYM and MLTSTR that will be returned. MLNewPacket(linkPointer); // Discard all packets until we get a RETURNPKT. while(MLNextPacket(linkPointer) != RETURNPKT) MLNewPacket(linkPointer); // Discard the return packet. MLNewPacket(linkPointer); success = NO; break; case DISPLAYPKT: // We shouldn't ever get one of these. MLNewPacket(linkPointer); success = NO; break; default: // Discard any mysterious packet. MLNewPacket(linkPointer); success = NO; break; } return success; } // Send "matrix" commands to Mathematica. - (BOOL)evaluateMatrixExpression:(char *)string resultType:(int)type result:(void**)result rows:(int *)numRows cols:(int *)numCols { char *commandString, *resultString, *symbol, *returnedString; BOOL success = YES; int packetType, packetTag, *returnedIntList, *nonVolatileIntList, row; long listCount; double *returnedRealList, *nonVolatileRealList, *returnedRow; double *returnedMatrix; commandString = malloc(strlen(string) + 50); switch(type) { case STRING: sprintf(commandString, "ToString[%s, PageWidth->70]", string); break; case DEFINITION: sprintf(commandString, "ToString[%s, PageWidth->70]", string); break; case INTEGERLIST: strcpy(commandString, string); break; case REALLIST: strcpy(commandString, string); break; case REALMATRIX: strcpy(commandString, string); break; default: success = NO; break; } // If an illegal type was specified, we'll return NO. if(!success) { free(commandString); return NO; } // Ship the command off to Mathematica. MLReturnValue = MLPutFunction(linkPointer, "ToExpression", 1); MLPutString(linkPointer, commandString); MLEndPacket(linkPointer); free(commandString); // Get the result of the execution of the command. packetType = MLNextPacket(linkPointer); switch(packetType) { case RETURNPKT: if(type == DEFINITION) { // Throw away anything returned. MLNewPacket(linkPointer); return NO; } packetTag = MLGetNext(linkPointer); switch(packetTag) { case MLTKSTR: if(MLGetString(linkPointer, &returnedString)) { resultString = (char *) malloc (strlen(returnedString) +1); strcpy(resultString, returnedString); *result = resultString; MLDisownString(linkPointer, returnedString); } else success = NO; break; case MLTKFUNC: switch(type) { case INTEGERLIST: if(MLGetIntegerList(linkPointer, &returnedIntList, &listCount)) { nonVolatileIntList = (int *)malloc(sizeof(int) * listCount); memcpy(nonVolatileIntList, returnedIntList, sizeof(int) * listCount); *result = nonVolatileIntList; *numCols = listCount; *numRows = 1; MLDisownIntegerList(linkPointer, returnedIntList, listCount); } break; case REALLIST: if(MLGetRealList(linkPointer, &returnedRealList, &listCount)) { nonVolatileRealList = (double*) malloc(sizeof(double) * listCount); memcpy(nonVolatileRealList, returnedRealList, sizeof(double) * listCount); *result = nonVolatileRealList; *numCols = listCount; *numRows = 1; MLDisownRealList(linkPointer, returnedRealList, listCount); } break; case REALMATRIX: returnedMatrix = (double *)malloc(*numRows * *numCols * sizeof(double)); MLGetNext(linkPointer); MLGetSymbol(linkPointer, &symbol); MLDisownSymbol(linkPointer, symbol); for(row = 0; row < *numRows; row++) { MLGetNext(linkPointer); MLGetRealList(linkPointer, &returnedRow, &listCount); memcpy(returnedMatrix+(row * *numCols), returnedRow, *numCols * sizeof(double)); MLDisownRealList(linkPointer, returnedRow, listCount); } *result = returnedMatrix; break; default: success = NO; break; } break; default: success = NO; break; } break; case MESSAGEPKT: // Discard the MLTKSYM and MLTSTR that will be returned. MLNewPacket(linkPointer); // Discard all packets until we get a RETURNPKT. while(MLNextPacket(linkPointer) != RETURNPKT) MLNewPacket(linkPointer); // Discard the return packet. MLNewPacket(linkPointer); success = NO; break; case DISPLAYPKT: // We shouldn't ever get one of these. MLNewPacket(linkPointer); success = NO; break; default: // Discard any mysterious packet. MLNewPacket(linkPointer); success = NO; break; } return success; } void error(MLINK linkPointer) { printf("\nerror: %s\n", MLErrorMessage(linkPointer)); MLClose(linkPointer); } void readAndPrintExpression(MLINK linkPointer) { char *s; long len; int n, i; double r; static int indent; switch (MLGetNext(linkPointer)) { case MLTKSYM: printf("MLTSYM\n"); MLGetSymbol(linkPointer, &s); printf("%s\n", s); break; case MLTKSTR: printf("MLTKSTR\n"); MLGetString( linkPointer, &s); printf("%s\n", s); break; case MLTKINT: printf("MLTKINT\n"); MLGetInteger(linkPointer, &n); printf("%d\n", n); break; case MLTKREAL: printf("MLTKREAL\n"); MLGetReal(linkPointer, &r); printf("%f\n", r); break; case MLTKFUNC: printf("MLTKFUNC\n"); indent += 3; printf("\n %*.*s", indent, indent, ""); if (MLGetArgCount( linkPointer, &len) == 0) error( linkPointer); else { readAndPrintExpression(linkPointer); printf("["); for (i = 1; i <= len; ++i) { readAndPrintExpression(linkPointer); if (i != len) printf(", "); } printf("]"); } indent -= 3; break; case MLTKERROR: default: printf("MLTKERROR\n"); error(linkPointer); } } int readPacket(MLINK linkPointer) { int packetTag; int length = 1; switch (packetTag = MLNextPacket(linkPointer)) { case INPUTPKT: printf("<INPUTPKT>\n"); break; case TEXTPKT: printf("<TEXTPKT>\n"); break; case RETURNPKT: printf("<RETURNPKT>\n"); break; case RETURNTEXTPKT: printf("<RETURNTEXTPKT>\n"); break; case MESSAGEPKT: length = 2; printf("<MESSAGEPKT>\n"); break; case CALLPKT: printf("<CALLPKT>\n"); break; case INPUTNAMEPKT: printf("<INPUTNAMEPKT>\n"); break; case OUTPUTNAMEPKT: printf("<OUTPUTNAMEPKT>\n"); break; case SYNTAXPKT: printf("<SYNTAXERROR>\n"); break; case MENUPKT: printf("<MENUPKT>\n"); break; case DISPLAYPKT: printf("<DISPLAYPKT>\n"); break; case DISPLAYENDPKT: printf("<DISPLAYENDPKT>\n"); break; default: printf("unknown packet \"%d\"\n", packetTag); return 0; } while (length --) readAndPrintExpression(linkPointer); if ((packetTag != INPUTNAMEPKT) && (packetTag != OUTPUTNAMEPKT)) printf("\n"); return packetTag; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.