Manipulating Expressions in External Programs

Wolfram Language expressions provide a very general way to handle all kinds of data, and you may sometimes want to use such expressions inside your external programs. A language like C, however, offers no direct way to store general Wolfram Language expressions. It is nevertheless possible to do this by using the loopback links provided by the Wolfram Symbolic Transfer Protocol (WSTP) library. A loopback link is a local WSTP connection inside your external program, to which you can write expressions that can later be read back.

WSLINKWSLoopbackOpen(stdenv,int*errno)
open a loopback link
voidWSClose(WSLINK link)close a link
intWSTransferExpression(WSLINK dest,WSLINK src)get an expression from src and put it onto dest

Functions for manipulating loopback links.

This opens a loopback link.
...
wstp = WSLoopbackOpen(stdenv, &errno);
This puts the expression Power[x,3] onto the loopback link.
WSPutFunction(wstp, "Power", 2);
WSPutSymbol(wstp, "x");
WSPutInteger32(wstp, 3);
...
This gets the expression back from the loopback link.
WSGetFunction(wstp, &head, &n);
WSGetSymbol(wstp, &sname);
WSGetInteger32(wstp, &k);
...
This closes the loopback link again.
WSClose(wstp);

You can use WSTransferExpression() to take an expression that you get via stdlink from the Wolfram Language, and save it in a local loopback link for later processing.

You can also use WSTransferExpression() to take an expression that you have built up on a local loopback link, and transfer it back to the Wolfram Language via stdlink.

This puts onto a local loopback link.
...
WSPutFunction(wstp, "Factorial", 1);
WSPutInteger32(wstp, 21);
This sends the head FactorInteger to the Wolfram Language.
WSPutFunction(stdlink, "FactorInteger", 1);
This transfers the from the loopback link to stdlink.
WSTransferExpression(stdlink, wstp);

You can put any sequence of expressions onto a loopback link. Usually you get the expressions off the link in the same order as you put them on.

And once you have got an expression off the link it is usually no longer saved. But by using WSCreateMark() you can mark a particular position in a sequence of expressions on a link, forcing WSTP to save every expression after the mark so that you can go back to it later.

WSMARKWSCreateMark(WSLINK link)create a mark at the current position in a sequence of expressions on a link
WSSeekMark(WSLINK link,WSMARK mark,int n)
go back to a position n expressions after the specified mark on a link
WSDestroyMark(WSLINK link,WSMARK mark)destroy a mark in a link

Setting up marks in WSTP links.

This puts the integer onto a loopback link.
...
WSPutInteger32(wstp, 45);
This puts onto the link.
WSPutInteger32(wstp, 33);
And this puts .
WSPutInteger32(wstp, 76);
This will read from the link. The will no longer be saved.
WSGetInteger32(wstp, &i);
This creates a mark at the current position on the link.
mark = WSCreateMark(wstp);
This will now read .
WSGetInteger32(wstp, &i);
And this will read .
WSGetInteger32(wstp, &i);
This goes back to the position of the mark.
WSSeekMark(wstp, mark, 0);
Now this will read again.
WSGetInteger32(wstp, &i);
It is important to destroy marks when you have finished with them, so no unnecessary expressions will be saved.
WSDestroyMark(wstp, mark);

The way the WSTP library is implemented, it is very efficient to open and close loopback links, and to create and destroy marks in them. The only point to remember is that as soon as you create a mark on a particular link, WSTP will save subsequent expressions that are put on that link, and will go on doing this until the mark is destroyed.

intWSGetNext(WSLINK link)find the type of the next object on a link
intWSGetArgCount(WSLINK link,int*n)store in n the number of arguments for a function on a link
intWSGetSymbol(WSLINK link,char**name)get the name of a symbol
intWSGetInteger32(WSLINK link,int*i)get a machine integer
intWSGetReal64(WSLINK link,double*x)get a machine floatingpoint number
intWSGetString(WSLINK link,char**string)get a character string

Functions for getting pieces of expressions from a link.

WSTKFUNCcomposite functionhead and arguments
WSTKSYMWolfram Language symbol
WSTKINTinteger
WSTKREALfloatingpoint number
WSTKSTRcharacter string

Constants returned by WSGetNext().

switch(WSGetNext(wstp)) {
This reads a composite function.
    case WSTKFUNC:
WSGetArgCount(wstp, &n);
recurse for head
for (i = 0; i < n; i++)
recurse for each argument

This reads a single symbol.
    case WSTKSYM:
WSGetSymbol(wstp, &name);
This reads a machine integer.
    case WSTKINT:
WSGetInteger32(wstp, &i);

}

By using it is straightforward to write programs that can read any expression. The way WSTP works, the head and arguments of a function appear as successive expressions on the link, which you read one after another.

Note that if you know that the head of a function will be a symbol, then you can use instead of . In this case, however, you still need to call to disown the memory used to store the symbol name.

intWSPutNext(WSLINK link,int type)prepare to put an object of the specified type on a link
intWSPutArgCount(WSLINK link,int n)give the number of arguments for a composite function
intWSPutSymbol(WSLINK link,char*name)
put a symbol on the link
intWSPutInteger32(WSLINK link,int i)put a machine integer
intWSPutReal64(WSLINK link,double x)put a machine floatingpoint number
intWSPutString(WSLINK link,char*string)
put a character string

Functions for putting pieces of expressions onto a link.

WSPutNext() specifies types of expressions using constants such as from the header filejust like WSGetNext().