Portability of MathLink Programs
The
Mathematica side of a
MathLink connection is set up to work exactly the same on all computer systems. But inevitably there are differences between external programs on different computer systems.
For a start, different computer systems almost always require different executable binaries. When you call
Install["prog"], therefore, you must be sure that
prog corresponds to a program that can be executed on your particular computer system.
| Install["file"] | try to execute file directly |
| Install["file",LinkProtocol->"type"] |
| use the specified protocol for low-level data transport |
| $SystemID | identify the type of computer system being used |
| Install["dir"] | try to execute a file with a name of the form dir/$SystemID/dir |
Installing programs on different computer systems.
Mathematica follows the convention that if
prog is an ordinary file, then
Install["prog"] will just try to execute it. But if
prog is a directory, then
Mathematica will look for a subdirectory of that directory whose name agrees with the current value of
$SystemID, and will then try to execute a file named
prog within that subdirectory.
| mcc -o prog... | put compiled code in the file prog in the current directory |
| mcc -xo prog... | put compiled code in prog/$SystemID/prog |
Typical Unix commands for compiling external programs.
Even though the executable binary of an external program is inevitably different on different computer systems, it can still be the case that the source code in a language such as C from which this binary is obtained can be essentially the same.
But to achieve portability in your C source code there are several points that you need to watch.
For a start, you should never make use of extra features of the C language or C run-time libraries that happen to be provided on a particular system, but are not part of standard C. In addition, you should try to avoid dealing with segmented or otherwise special memory models.
The include file
mathlink.h contains standard C prototypes for all the functions in the
MathLink library.
MathLink functions that use specific C types.
If you are going to call
MathLink library functions in a portable way, it is essential that you use the same types as they do.
If your programs correctly match the argument types for the
MathLink library functions, you do not have to worry about C type differences between computer systems.
MathLink automatically converts the C types to the appropriate sizes for each platform.
MathLink also swaps bytes as needed to correctly transfer numbers across platforms, and it converts between floating-point number formats with the smallest possible loss of precision.
| MLPutString(stdlink,char*s) | put a null-terminated C character string |
| MLPutUnicodeString(stdlink,unsigned short*s,int n) |
| put a string encoded in terms of 16-bit UCS-2 Unicode characters |
| MLPutByteString(stdlink,unsigned char*s,int n) |
| put a string containing only 8-bit character codes |
| MLPutUTF8String(stdlink, const unsigned char*s,int n) | put a string of UTF-8 encoded Unicode characters |
| MLPutUTF16String(stdlink, const unsigned short*s,int n) | put a string of UTF-16 encoded Unicode characters |
| MLPutUTF32String(stdlink, const unsigned int*s,int n) | put a string of UTF-32 encoded Unicode characters |
| MLGetString(stdlink,char**s) | get a null-terminated C character string |
| MLGetUnicodeString(stdlink,unsigned short**s,long*n) |
| get a string encoded in terms of 16-bit UCS-2 Unicode characters |
| MLGetByteString(stdlink,unsigned char**s,long*n,long spec) |
| get a string containing only 8-bit character codes, using spec as the code for all 16-bit characters |
| MLGetUTF8String(stdlink, const unsigned char**s,int*m,int*n) | get a string of UTF-8 encoded Unicode characters |
| MLGetUTF16String(stdlink, const unsigned short**s,int*m,int*n) | get a string of UTF-16 encoded Unicode characters |
| MLGetUTF32String(stdlink, const unsigned int**s,int*n) | get a string of UTF-32 encoded Unicode characters |
Manipulating general strings.
In simple C programs, it is typical to use strings that contain only ordinary ASCII characters. But in
Mathematica it is possible to have strings containing all sorts of special characters. These characters are specified within
Mathematica using Unicode character codes, as discussed in
"Raw Character Encodings".
C language
char* strings typically use only 8 bits to store the code for each character. UCS-2 encoded strings, however, require 16 bits. As a result, the functions
MLPutUnicodeString() and
MLGetUnicodeString() work with arrays of
unsignedshort integers. The same is true of UTF-16 encoded strings and the corresponding functions
MLPutUTF16String() and
MLGetUTF16String().
UTF-32 encoded strings require 32 bits for each character, and the corresponding functions
MLPutUTF32String() and
MLGetUTF32String() work with arrays of
unsigned int integers.
If you know that your program will not have to handle special characters, then you may find it convenient to use
MLPutByteString() and
MLGetByteString(). These functions represent all characters directly using 8-bit character codes. If a special character is sent from
Mathematica, then it will be converted by
MLGetByteString() to a fixed code that you specify.
| • main() may need to be different on different computer systems |
A point to watch in creating portable MathLink programs.
Computer systems and compilers that have C run-time libraries based on the Unix model allow
MathLink programs to have a main program of the form
main(argc, argv) which simply calls
MLMain(argc, argv).
Some computer systems or compilers may however require main programs of a different form. You should realize that you can do whatever initialization you want inside
main() before calling
MLMain(). Once you have called
MLMain(), however, your program will effectively go into an infinite loop, responding to requests from
Mathematica until the link to it is closed.