WSTP Development in C (Mac OS X)

This document describes how to compile and run Wolfram Symbolic Transfer Protocol (WSTP) programs written in the C language on Mac OS X systems. ("WSTP and External Program Communication" describes how to write WSTP programs in both the Wolfram Language and the C language.)

This document does not teach you, in general, how to use your compiler and other development tools, nor does it teach you how to program in C. If you have any trouble building or running your WSTP programs, see "Troubleshooting" at the end of this document.

Most of what is described in this document is Unix specific and is applicable to all supported Unix platforms. However, there may be some information which is specific to Mac OS X machines. To learn how to compile and run WSTP programs for another platform, see the Developer Guide for that platform.

Supported Development Platforms

The wstp.framework shared library in the WSTP Developer Kit (WSDK) for Mac OS X can be used for Mac OS X 10.9.0 and newer and Xcode 6.x and newer. The framework includes universal binary support for 32-bit x86 and 64-bit x86 architectures.

Installing the WSTP Components

The WSTP Developer Kit is located in the (RefLink[$InstallationDirectory, paclet:ref/$InstallationDirectory])/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64 directory within your Wolfram System directory.

Recommended Installation

CompilerAdditions Installation

The WSTP components that you will need to build WSTP programs have already been installed in the Wolfram System bundle. One way to use these components is to leave them in the Mathematica.app directory and specify their full pathname when you call your compiler. This approach is taken in the example "makefiles" in the section "Building WSTP Programs".

An alternative is to copy these components (wstp.h, libWSTPi4.a, and wstp.framework) into directories in which your compiler will automatically search for such files. These directories are commonly /usr/include or /usr/lib for wstp.h and libWSTPi4.a, respectively, and /Library/Frameworks or ~/Library/Frameworks for wstp.framework. On many systems not all users have write access to these directories.

WSTPExamples Installation

Copy the WSTPExamples directory to your home directory.

WSTP Framework Components

The following is a description of each file or directory in the WSDK.

CompilerAdditions Directory

wstp.h

wstp.h is the header file that must be included in your C and C++ source files. It should be placed where your compiler can find it. You could copy this header file into the same directory as your source files, copy it into the same location as the standard header files, or leave it where it is if you added the WSTP directory to the search path for header files.

libWSTPi4.a

libWSTPi4.a is the static library that contains all of the WSTP functions. It should be included in your project. You could copy this library into the same directory as your source files or leave it where it is if you added the WSTP directory to the search path for libraries.

wstp.framework

wstp.framework is the dynamic library framework that contains all the WSTP functions. Use the framework when you want to build a version of your program that links dynamically with the WSTP library. You could copy this library in the same directory as your source files or leave it where it is if you added the WSTP directory to the framework search paths.

wsprep

(RefLink[wsprep, paclet:ref/program/wsprep]) is an application that writes WSTP programs automatically by processing "template" files. It may be convenient to copy this application into the same directory as your project or to create an alias to it.

wscc

(RefLink[wscc, paclet:ref/program/wscc]) is a script that preprocesses and compiles your WSTP source files.

WSTPExamples Directory

This directory contains the source code for some very simple WSTP programs. By using this source code, you can learn how to build and run WSTP programs without having to write any code yourself.

PrebuiltExamples Directory

This directory contains prebuilt versions of the example programs. "Running WSTP Programs" describes how to run two of these programs. "Building WSTP Programs" describes how to build them yourself using the source code in the WSTPExamples directory.

Building WSTP Programs

The general procedure for building WSTP programs is to include wstp.h in any C or C++ source files that make WSTP function calls, to compile your source files, and then to link the resulting object code with the libWSTPi4.a library or wstp.framework and any other standard libraries required by your application. If your application uses the WSTP template mechanism, then your template files must first be processed into a C source file using (RefLink[wsprep, paclet:ref/program/wsprep]).

Using WSTP Template Files

If your program uses the WSTP template mechanism as described in "WSTP and External Program Communication", you must simultaneously preprocess source files containing template entries using the (RefLink[wsprep, paclet:ref/program/wsprep]) application. (A template entry is a sequence of lines that contain template keywords. Each entry defines a Wolfram Language function that when evaluated calls an associated C function.) When (RefLink[wsprep, paclet:ref/program/wsprep]) processes such source files, it converts template entries into C functions, without changing other text, and writes out additional C functions that implement a remote procedure call mechanism using WSTP. The result is a C source file that is ready for compilation.

For example, the command

wsprep addtwo.tm -o addtwotm.c

will produce a C source file addtwotm.c from the template entries and the other text remaining in addtwo.tm. You would then compile the output file using the C compiler. If you use the make utility to build your program, you could add a rule similar to the following to your makefile.

addtwotm.c  :  addtwo.tm
    wsprep  addtwo.tm  -o addtwotm.c

Building WSTP Programs from the Command Line

What follows is a sample makefile needed to build the sample programs in the WSDK, including addtwo and factor. To build a sample program, in this case addtwo, evaluate the following command in the WSTPExamples directory.

make addtwo

Using a Makefile

# This makefile can be used to build all or some of the sample
# programs. To build all of them, use the command
# 'make all'. To build one, say addtwo, use the command
# 'make addtwo'.

WSLINKDIR = /Applications/Mathematica.app/Contents/SystemFiles/Links/WSTP/DeveloperKit
SYS = MacOSX-x86-64
CADDSDIR = ${WSLINKDIR}/${SYS}/CompilerAdditions

INCDIR = ${CADDSDIR}
LIBDIR = ${CADDSDIR}

WSPREP = ${CADDSDIR}/wsprep

EXTRA_LIBS = -lc++ -framework Foundation

WSTP_LIB = -lWSTPi4

all : addtwo bitops counter factor factor2 factor3 quotient reverse sumalist

addtwo : addtwotm.o addtwo.o
	${CC} -I${INCDIR} addtwotm.o addtwo.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

bitops : bitopstm.o bitops.o
	${CC} -I${INCDIR} bitopstm.o bitops.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

counter : countertm.o
	${CC} -I${INCDIR} countertm.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor : factor.o
	${CC} -I${INCDIR} factor.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor2 : factor2.o
	${CC} -I${INCDIR} factor2.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor3 : factor3.o
	${CC} -I${INCDIR} factor3.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

quotient : quotient.o
	${CC} -I${INCDIR} quotient.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

reverse : reversetm.o
	${CC} -I${INCDIR} reversetm.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

sumalist : sumalisttm.o sumalist.o
	${CC} -I${INCDIR} sumalisttm.o sumalist.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

.c.o :
	${CC} -c -I${INCDIR} $<

addtwotm.c : addtwo.tm
	${WSPREP} $? -o $@

bitopstm.c : bitops.tm
	${WSPREP} $? -o $@

countertm.c : counter.tm
	${WSPREP} $? -o $@

reversetm.c : reverse.tm
	${WSPREP} $? -o $@

sumalisttm.c : sumalist.tm
	${WSPREP} $? -o $@

Library Dependencies

When building WSTP programs from the command line, developers must link with libc++ and the Foundation framework.

Building Mac OS X WSTP Programs with Xcode

Xcode 6.x+

Creating a Project for addtwo

To create a project that can be used to edit, build, and debug addtwo:

cd "/Applications/Mathematica.app/Contents/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64/WSTPExamples"

cp addtwo.tm addtwo.c ~/addtwo/

cd ~/addtwo/

/Applications/Mathematica.app/Contents/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64/CompilerAdditions/wsprep addtwo.tm -o addtwo.tm.c

Creating a Project for Factor

To create a project that can be used to edit, build, and debug factor:

cd "/Applications/Mathematica.app/Contents/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64/WSTPExamples"

cp factor.c ~/factor/

Using wscc

(RefLink[wscc, paclet:ref/program/wscc]) is a script that preprocesses and compiles your WSTP source files. It will preprocess WSTP templates in any file whose name ends with .tm, and then call cc on the resulting C source code. (RefLink[wscc, paclet:ref/program/wscc]) will pass command-line options and other files directly to cc. Following is a command that would build the addtwo application using (RefLink[wscc, paclet:ref/program/wscc]).

wscc addtwo.tm addtwo.c -o addtwo

Running WSTP Programs

The instructions in "Building WSTP Programs" describe how to build two WSTP programs using source code in the WSTPExamples directory. These two programs, addtwo and factor, are already built for you in the PrebuiltExamples folder. Before building them on your own, you should try to run the prebuilt examples to verify that the WSTP system additions are installed and working and to learn what to expect from these examples when they are properly built. The rest of the comments assume that you are using the programs found in the Developer Kit.

Running a Prebuilt Example from the Wolfram Language Kernel

The first example program, addtwo, is a WSTP template program that is installed into the Wolfram Language. That is, this program runs in the background, providing, as a service to the Wolfram Language, one or more externally compiled functions. To the Wolfram Language user, these functions appear to be built-in. In order to get this new functionality, the user of the Wolfram Language must run the (RefLink[Install, paclet:ref/Install])[] function. The addtwo program uses a template file that defines the Wolfram Language function AddTwo[] as a call to the C function addtwo(). (The template mechanism is described in "WSTP and External Program Communication".) The source code for this program looks likes this.

:Begin:
:Function:       addtwo
:Pattern:        AddTwo[i_Integer, j_Integer]
:Arguments:      { i, j }
:ArgumentTypes:  { Integer, Integer }
:ReturnType:     Integer
:End:

:Evaluate: AddTwo::usage = "AddTwo[x, y] gives the sum of two machine integers x and y."

int addtwo( int i, int j)
{
	return i+j;
}

int main(int argc, char* argv[])
{
	return WSMain(argc, argv);
}

Evaluate the following two cells:

SetDirectory[$InstallationDirectory<>"/SystemFiles/Links/WSTP/DeveloperKit/"<>$SystemID<>"/PrebuiltExamples"]

link = Install["./addtwo"]

To see a list of the newly available functions, evaluate the following cell:

LinkPatterns[link]

This displays the usage message for the AddTwo[] function as defined in the file addtwo.tm:

?AddTwo

Now try it:

AddTwo[2, 3]

See what happens if the sum of the two machine integers will not fit in a machine integer or if either argument is not a machine integer. (2^31-1 is the largest machine integer. If your compiler uses 2-byte integers, then 2^15-1 is the largest C int.)

AddTwo[2^31-1, 1]

The addtwo program is not prepared for big integers:

AddTwo[2^31, 1]

This does not match AddTwo[_Integer,_Integer]:

AddTwo[x, 1]

(RefLink[Install, paclet:ref/Install])[] called (RefLink[LinkOpen, paclet:ref/LinkOpen])[] and then exchanged information with the external program to set up the definition for AddTwo[]. You really do not have to worry about these details, but if you are curious, evaluate the following:

??AddTwo

When you are finished using the external program, evaluate the following:

Uninstall[link]

Invoking the Wolfram Language Kernel from within a Prebuilt Example

The second example program, factor, is a Wolfram System front end in the sense that the Wolfram Language kernel runs in the background providing, as a service to factor, the computational services of the kernel—in this case, the ability to factor an integer typed by the user. These examples assume that the Wolfram System is installed in the Applications directory.

Launch the "factor" application by executing the following command.

factor -linkmode launch -linkname '"/Applications/Mathematica.app/Contents/MacOS/WolframKernel" -wstp'

After a moment, a prompt will appear requesting that you type an integer. Type an integer with fewer than 10 digits and press the Return key. (The other factor examples relax the restriction on the size of integer you may type in.)

Integer to factor:

The prime factors returned by the Wolfram Language are printed, and factor closes its link with the Wolfram Language.

Integer to factor: 123456789
3 ^ 2
3607 ^ 1
3803 ^ 1

Supported Link Protocols

The C function (NonWLLink[WSOpenArgcArgv(), paclet:ref/c/WSOpenArgcArgv]) and the Wolfram Language function (RefLink[LinkOpen, paclet:ref/LinkOpen])[] are documented in "WSTP and External Program Communication". On Macintosh OS X machines, the legal values for the (RefLink[LinkProtocol, paclet:ref/LinkProtocol]) option are TCPIP, TCP, SharedMemory, Pipes, and IntraProcess. A (RefLink[LinkProtocol, paclet:ref/LinkProtocol]) is the mechanism used to transport data from one end of a connection to the other. SharedMemory is the default protocol for LinkMode->Launch links. SharedMemory is the default for LinkMode->Listen and LinkMode->Connect links.

Note that link names are unsigned 16-bit integers for the TCPIP and TCP protocols. Even though "TCPIP" link names are integers, they are still given as strings (of digits) to (NonWLLink[WSOpenArgcArgv(), paclet:ref/c/WSOpenArgcArgv]) and (RefLink[LinkOpen, paclet:ref/LinkOpen])[].

Troubleshooting