Running Mathematica from Within an External Program
To run
Mathematica from within an external program requires making use of many general features of
MathLink. The first issue is how to establish a
MathLink connection to
Mathematica.
When you use
MathLink templates to create external programs that can be called from
Mathematica, source code to establish a
MathLink connection is automatically generated, and all you have to do in your external program is to call
MLMain(argc, argv). But in general you need to call several functions to establish a
MathLink connection.
| MLENVMLInitialize(0) | initialize MathLink library functions |
| MLINKMLOpenArgcArgv(MLENV env,int argc,char**argv,int*errno) |
| open a MathLink connection taking parameters from an argv array |
| MLINKMLOpenString(MLENV env,char*string,int*errno) |
| open a MathLink connection taking parameters from a single character string |
| intMLActivate(MLINK link) | activate a MathLink connection, waiting for the program at the other end to respond |
| voidMLClose(MLINK link) | close a MathLink connection |
| voidMLDeinitialize(MLENV env) | deinitialize MathLink library functions |
Opening and closing MathLink connections.
Include the standard MathLink header file.
int main(int argc, char *argv[]) {
MLENV env; MLINK link; int errno;
|
This initializes MathLink library functions. |
This opens a MathLink connection, using the same arguments as were passed to the main program.
link = MLOpenArgcArgv(env, argc, argv, &errno);
|
This activates the connection, waiting for the other program to respond. |
Often the
argv that you pass to
MLOpenArgcArgv() will come directly from the
argv that is passed to
main() when your whole program is started.
The elements in the
argv array are character strings which mirror the arguments and options used in the
Mathematica functions
LinkLaunch,
LinkCreate and
LinkConnect.
| "-linklaunch" | operate like LinkLaunch["name"] |
| "-linkcreate" | operate like LinkCreate["name"] |
| "-linkconnect" | operate like LinkConnect["name"] |
| "-linkname","name" | give the name to use |
| "-linkprotocol","protocol" | give the link protocol to use (TCPIP, Pipes, etc.) |
Possible elements of the argv array passed to MLOpenArgcArgv().
As an alternative to
MLOpenArgcArgv() you can use
MLOpenString(), which takes parameters concatenated into a single character string with spaces in between.
Once you have successfully opened a
MathLink connection to the
Mathematica kernel, you can then use standard
MathLink functions to exchange data with it.
Functions often used in communicating with the Mathematica kernel.
Once you have sent all the pieces of a packet using
MLPutFunction() etc.,
MathLink requires you to call
MLEndPacket() to ensure synchronization and consistency.
One of the main issues in writing an external program which communicates directly with the
Mathematica kernel is handling all the various kinds of packets that the kernel can generate.
The function
MLNextPacket() finds the head of the next packet that comes from the kernel, and returns a constant that indicates the type of the packet.
Some packets recognized by MLNextPacket().
This keeps on reading data from a link, discarding it until an error or a ReturnPacket is found.
while ((p = MLNextPacket(link)) && p RETURNPKT) MLNewPacket(link);
|
If you want to write a complete front end to
Mathematica, you will need to handle all of the possible types of packets that the kernel can generate. Typically you can do this by setting up an appropriate
switch on the value returned by
MLNextPacket().
The
MathLink Developer Kit contains sample source code for several simple but complete front ends.
| intMLReady(MLINK link) | test whether there is data waiting to be read on a link |
| int MLReadyParallel (MLENV e, MLINK *links, int n, mltimeval t) |
| test in parallel whether there is data to be read from a list of links |
| intMLFlush(MLINK link) | flush out buffers containing data waiting to be sent on a link |
Flow of data on links.
One feature of more sophisticated external programs such as front ends is that they may need to perform operations while they are waiting for data to be sent to them by
Mathematica. When you call a standard
MathLink library function such as
MLNextPacket() your program will normally block until all the data needed by this function is available.
You can avoid blocking by repeatedly calling
MLReady(), and only calling functions like
MLNextPacket() when
MLReady() no longer returns
0.
MLReady() is the analog of the
Mathematica function
LinkReadyQ.
Note that
MathLink sometimes buffers the data that you tell it to send. To make sure that all necessary data has been sent you should call
MLFlush(). Only after doing this does it make sense to call
MLReady() and wait for data to be sent back.