# Handling Lists, Arrays, and Other Expressions

*MathLink* allows you to exchange data of any type with external programs. For more common types of data, you simply need to give appropriate or specifications in your *MathLink* template file.

Mathematica specification | C specification | |

Integer | integer | int |

Real | floating-point number | double |

IntegerList | list of integers | int*,long |

RealList | list of floating-point numbers | double*,long |

String | character string | char* |

Symbol | symbol name | char* |

Manual | call MathLink routines directly | void |

:Begin:

:Function: h

:Pattern: h[a_List]

:Arguments: {a}

:ArgumentTypes: {IntegerList}

:ReturnType: Integer

:End:

int h(int *a, long alen) {

int i, tot=0;

for(i=0; i<alen; i++)

tot += a[i];

return tot;

}

In[1]:= |

Out[1]= |

In[2]:= |

Out[2]= |

In[3]:= |

Out[3]= |

In[4]:= |

Out[4]= |

You can mix basic types of arguments in any way you want. Whenever you use or , however, you have to include an extra argument in your C program to represent the length of the list.

:ArgumentTypes: {IntegerList, RealList, Integer}

void f(int *a, long alen, double *b, long blen, int c)

Note that when a list is passed to a C program by *MathLink* its first element is assumed to be at position 0, as is standard in C, rather than at position 1, as is standard in *Mathematica*.

In addition, following C standards, character strings specified by String are passed as objects, terminated by null bytes. "Portability of *MathLink* Programs" discusses how to handle special characters.

MLPutInteger32(stdlink,int i) | put a single integer |

MLPutReal64(stdlink,double x) | put a single floating-point number |

MLPutInteger32List(stdlink,int*a,int n) | |

put a list of n integers starting from location a | |

MLPutReal64List(stdlink,double*a,int n) | |

put a list of n floating-point numbers starting from location a | |

MLPutInteger32Array(stdlink,int*a,int*dims,NULL,int d) | |

put an array of integers to form a depth d list with dimensions dims | |

MLPutReal64Array(stdlink,double*a,int*dims,NULL,int d) | |

put an array of floating-point numbers | |

MLPutString(stdlink,char*s) | put a character string |

MLPutSymbol(stdlink,char*s) | put a character string as a symbol name |

MLPutFunction(stdlink,char*s,int n) | |

begin putting a function with head s and n arguments |

*MathLink* functions for sending data to *Mathematica*.

When you use a *MathLink* template file, what mprep and mcc actually do is to create a C program that includes explicit calls to *MathLink* library functions. If you want to see an example of how to use the *MathLink* library functions directly, you can look at the source code of this program. Note when you use mcc, you typically need to give a option, otherwise the source code that is generated is automatically deleted.

If your external function just returns a single integer or floating-point number, then you can specify this just by giving Integer or Real as the in your *MathLink* template file. But because of the way memory allocation and deallocation work in C, you cannot directly give specifications such as or . And instead, to return such structures, you must explicitly call *MathLink* library functions within your C program, and give Manual as the specification.

*MathLink*template for a function that takes an integer as an argument, and returns a list of the digits in its binary representation using explicit

*MathLink*functions.

:Begin:

:Function: bits

:Pattern: bits[i_Integer]

:Arguments: {i}

:ArgumentTypes: {Integer}

:ReturnType: Manual

:End:

void bits(int i) {

int a[32], k;

for(k=0; k<32; k++) {

a[k] = i%2;

i >>= 1;

if (i==0) break;

}

if (k<32) k++;

MLPutInteger32List(stdlink, a, k);

return ;

}

In[5]:= |

Out[5]= |

In[6]:= |

Out[6]= |

If you declare an array in C as , then you can use MLPutInteger32Array() to send it to *Mathematica* as a depth 3 list.

int a[8][16][100];

int dims[] = {8, 16, 100};

MLPutInteger32Array(stdlink, a, dims, NULL, 3);

You can use *MathLink* functions to create absolutely any *Mathematica* expression. The basic idea is to call a sequence of *MathLink* functions that correspond directly to the FullForm representation of the *Mathematica* expression.

MLPutFunction(stdlink, "Plus", 2);

MLPutInteger32(stdlink, 77);

MLPutSymbol(stdlink, "x");

In general, you first call MLPutFunction(), giving the head of the *Mathematica* function you want to create, and the number of arguments it has. Then you call other *MathLink* functions to fill in each of these arguments in turn. "Expressions" discusses the general structure of *Mathematica* expressions and the notion of heads.

MLPutFunction(stdlink, "List", 2);

MLPutInteger32List(stdlink, r, 10);

MLPutFunction(stdlink, "List", 2);

MLPutReal64(stdlink, 4.5);

MLPutInteger32(stdlink, 11);

MLPutInteger32Array() and MLPutReal64Array() allow you to send arrays which are laid out in memory in the one-dimensional way that C pre-allocates them. But if you create arrays during the execution of a C program, it is more common to set them up as nested collections of pointers. You can send such arrays to *Mathematica* by using a sequence of MLPutFunction() calls, ending with an MLPutInteger32List() call.

int ***a;

MLPutFunction(stdlink, "List", n1);

for (i=0; i<n1; i++) {

MLPutFunction(stdlink, "List", n2);

for (j=0; j<n2; j++) {

MLPutInteger32List(stdlink, a[i][j], n3);

}

}

It is important to realize that any expression you create using *MathLink* functions will be evaluated as soon as it is sent to *Mathematica*. This means, for example, that if you wanted to transpose an array that you were sending back to *Mathematica*, all you would need to do is to wrap a Transpose around the expression representing the array. You can then do this simply by calling MLPutFunction(stdlink, "Transpose", 1); just before you start creating the expression that represents the array.

The idea of postprocessing data that you send back to *Mathematica* has many uses. One example is as a way of sending lists whose length you do not know in advance.

In[7]:= |

Out[7]= |

In[8]:= |

Out[8]= |

In[9]:= |

Out[9]= |

In[10]:= |

Out[10]= |

In order to call MLPutInteger32List(), you need to know the length of the list you want to send. But by creating a sequence of nested Sequence objects, you can avoid having to know the length of your whole list in advance.

MLPutFunction(stdlink, "List", 1);

while( condition ) {

/* generate an element */

MLPutFunction(stdlink, "Sequence", 2);

` MLPutInteger32(stdlink, i );`

}

MLPutFunction(stdlink, "Sequence", 0);

MLGetInteger32(stdlink,int*i) | get an integer, storing it at address |

MLGetReal64(stdlink,double*x) | get a floating-point number, storing it at address |

Basic functions for explicitly getting data from *Mathematica*.

*MathLink* provides functions like MLPutInteger32() to send data from an external program into *Mathematica*. *MathLink* also provides functions like MLGetInteger32() that allow you to get data from *Mathematica* into an external program.

The list that you give for in a *MathLink* template can end with Manual, indicating that after other arguments have been received, you will call *MathLink* functions to get additional expressions.

:Begin:

:Function: f

:Pattern: f[i_Integer, x_Real, y_Real]

:Arguments: {i, x, y}

:ArgumentTypes: {Integer, Manual}

:ReturnType: Real

:End:

double f(int i) {

double x, y;

MLGetReal64(stdlink, &x);

MLGetReal64(stdlink, &y);

return i+x+y;

}

*MathLink* functions such as MLGetInteger32(link, pi) work much like standard C library functions such as . The first argument specifies the link from which to get data. The last argument gives the address at which the data that is obtained should be stored.

MLCheckFunction(stdlink,"name",int*n) | |

check the head of a function and store how many arguments it has |

Getting a function via *MathLink*.

:Begin:

:Function: f

:Pattern: f[a:{___Integer}]

:Arguments: {a}

:ArgumentTypes: {Manual}

:ReturnType: Integer

:End:

int f(void) {

int n, i;

int a[MAX];

MLCheckFunction(stdlink, "List", &n);

for (i=0; i<n; i++)

MLGetInteger32(stdlink, a+i);

In simple cases, it is usually possible to ensure on the *Mathematica* side that the data you send to an external program has the structure that is expected. But in general the return value from MLCheckFunction() will be MLSUCCESS only if the data consists of a function with the name you specify.

Note that if you want to get a nested collection of lists or other objects, you can do this by making an appropriate sequence of calls to MLCheckFunction().

MLGetInteger32List(stdlink,int**a,int*n) | |

get a list of integers, allocating the memory needed to store it | |

MLGetReal64List(stdlink,double**a,int*n) | |

get a list of floating-point numbers | |

MLReleaseInteger32List(stdlink,int*a,int n) | |

release the memory associated with a list of integers | |

MLReleaseReal64List(stdlink,double*a,int n) | |

release the memory associated with a list of floating-point numbers |

When an external program gets data from *Mathematica*, it must set up a place to store the data. If the data consists of a single integer, as in MLGetInteger32(stdlink, &n), then it suffices just to have declared this integer using .

But when the data consists of a list of integers of potentially any length, memory must be allocated to store this list at the time when the external program is actually called.

MLGetInteger32List(stdlink, &a, &n) will automatically do this allocation, setting a to be a pointer to the result. Note that memory allocated by functions like MLGetInteger32List() is always in a special reserved area, so you cannot modify or free it directly.

int f(void) {

int n;

int *a;

MLGetInteger32List(stdlink, &a, &n);

MLReleaseInteger32List(stdlink, a, n);

...

}

If you use as an specification, then *MathLink* will automatically release the memory used for the list after your external function exits. But if you get a list of integers explicitly using MLGetInteger32List(), then you must not forget to release the memory used to store the list after you have finished with it.

MLGetInteger32Array(stdlink,int**a,int**dims,char***heads,int*d) | |

get an array of integers of any depth | |

MLGetReal64Array(stdlink,double**a,int**dims,char***heads,int*d) | |

get an array of floating-point numbers of any depth | |

MLReleaseInteger32Array(stdlink,int*a,int*dims,char**heads,int d) | |

release memory associated with an integer array | |

MLReleaseReal64Array(stdlink,double*a,int*dims,char**heads,int d) | |

release memory associated with a floating-point array |

MLGetInteger32List() extracts a one-dimensional array of integers from a single *Mathematica* list. MLGetInteger32Array() extracts an array of integers from a collection of lists or other *Mathematica* functions nested to any depth.

The name of the *Mathematica* function at level i in the structure is stored as a string in . The size of the structure at level i is stored in , while the total depth is stored in d.

If you pass a list of complex numbers to your external program, then MLGetReal64Array() will create a two-dimensional array containing a sequence of pairs of real and imaginary parts. In this case, heads[0] will be "List" while heads[1] will be .

Note that you can conveniently exchange arbitrary-precision numbers with external programs by converting them to lists of digits in *Mathematica* using IntegerDigits and RealDigits.

MLGetString(stdlink,char**s) | get a character string |

MLGetSymbol(stdlink,char**s) | get a symbol name |

MLReleaseString(stdlink,char*s) | release memory associated with a character string |

MLReleaseSymbol(stdlink,char*s) | release memory associated with a symbol name |

Getting character strings and symbol names.

If you use String as an specification, then *MathLink* will automatically release the memory that is used to store the string after your function exits. This means that if you want to continue to refer to the string, you must allocate memory for it, and explicitly copy each character in it.

If you get a string using MLGetString(), however, then *MathLink* will not automatically release the memory used for the string when your function exits. As a result, you can continue referring to the string. Be careful not to modify the contents of the string by writing to the memory that is returned by MLGetString(). When you no longer need the string, you must nevertheless explicitly call MLReleaseString() in order to release the memory associated with it.

MLGetFunction(stdlink,char**s,int*n) | |

begin getting a function, storing the name of the head in s and the number of arguments in n | |

MLReleaseSymbol(stdlink,char*s) | release memory associated with a function name |

Getting an arbitrary function.

If you know what function to expect in your external program, then it is usually simpler to call MLCheckFunction(). But if you do not know what function to expect, you have no choice but to call MLGetFunction(). If you do this, you need to be sure to call MLReleaseSymbol() to release the memory associated with the name of the function that is found by MLGetFunction().