WSTP Development in C (Linux)
Supported Development Platforms | Running WSTP Programs |
Installing the WSTP Components | Troubleshooting |
Building WSTP Programs |
This document describes how to compile and run Wolfram Symbolic Transfer Protocol (WSTP) programs written in the C language on Linux 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 the "Troubleshooting" section at the end of this document.
Most of what is described in this document is Linux specific, and is applicable to all supported Linux platforms. To learn how to compile and run WSTP programs for another platform, see the Developer Guide for that platform.
As a shared library, WSTP can be used with any development environment that adheres to the standard calling conventions and binary interfaces as specified by the following compilers listed.
While some of the following compilers integrate with integrated development environments produced by the compiler creators, they also function equally well with a make utility.
C compiler | C++ compiler | ||
"Linux" | gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) | g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) | |
"Linux-x86-64" | gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) | g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) |
In addition to the above, compiling the WSTP API requires libuuid development library, referred to as uuid-dev on Debian systems, and libuuid-devel on Red Hat and Suse.
The WSTP Developer Kit (WSDK) is located in the directory $InstallationDirectory/SystemFiles/Links/WSTP/DeveloperKit/$SystemID within your Wolfram System directory.
Recommended Installation
CompilerAdditions Installation
The WSTP components that you will need to build WSTP programs have already been installed by the Wolfram System installer. One way to use these components is to leave them in the Wolfram System directory and specify their full path name 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, libWSTP32i4.a, libWSTP32i4.so, libWSTP64i4.a, and libWSTP64i4.so) into directories in which your compiler will automatically search for such files. These directories are commonly /usr/include and /usr/lib, but may be different on your system. On many systems not all users have write access to these directories.
WSTPExamples Installation
WSTP Framework Components
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 that include it, or in 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.
libWSTP32i4.a/libWSTP64i4.a
This is the static library that contains all 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. The 32/64 indicates whether the library is a 32-bit or a 64-bit version of the WSTP library.
libWSTP32i4.so/libWSTP64i4.so
This is the dynamic shared 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, into a systemwide location such as /lib or /usr/lib, or leave it where it is if you added the WSTP directory to the search path for libraries. The 32/64 indicates whether the library is a 32-bit or a 64-bit version of the WSTP library.
wsprep
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
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 Folder
This folder 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 folder.
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 libWSTP32i4.a, libWSTP64i4.a, libWSTP32i4.so, or libWSTP64i4.so library 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 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 your source files that contain template entries using the 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 wsprep processes such source files, it converts template entries into C functions, passes other text through unmodified, 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.
will produce a C source file addtwotm.c from the template entries and other text 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 one to your makefile.
Building WSTP programs
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.
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'.
WSTPLINKDIR = /usr/local/Wolfram/Mathematica/11.2/SystemFiles/Links/WSTP/DeveloperKit
SYS = Linux # Set this value with the result of evaluating $SystemID
CADDSDIR = ${WSTPLINKDIR}/${SYS}/CompilerAdditions
INCDIR = ${CADDSDIR}
LIBDIR = ${CADDSDIR}
EXTRALIBS = -lm -lpthread -lrt -lstdc++ -ldl -libuuid # Set these with appropriate libs for your system.
WSTPLIB = WSTP32i4 # Set this to WSTP64i4 if using a 64-bit system
WSPREP = ${CADDSDIR}/wsprep
all : addtwo bitops counter factor factor2 factor3 quotient reverse sumalist
addtwo : addtwotm.o addtwo.o
${CC} -I${INCDIR} addtwotm.o addtwo.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
bitops : bitopstm.o bitops.o
${CC} -I${INCDIR} bitopstm.o bitops.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
counter : countertm.o
${CC} -I${INCDIR} countertm.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
factor : factor.o
${CC} -I${INCDIR} factor.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
factor2 : factor2.o
${CC} -I${INCDIR} factor2.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
factor3 : factor3.o
${CC} -I${INCDIR} factor3.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
quotient : quotient.o
${CC} -I${INCDIR} quotient.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
reverse : reversetm.o
${CC} -I${INCDIR} reversetm.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@
sumalist : sumalisttm.o sumalist.o
${CC} -I${INCDIR} sumalisttm.o sumalist.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -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 $@
Use the following table to determine the extra libraries needed for linking WSTP programs on your system.
$SystemID | EXTRALIBS | |
"Linux" | -lm -lpthread -lrt -lstdc++ -ldl -luuid | |
"Linux-x86-64" | -lm -lpthread -lrt -lstdc++ -ldl -luuid |
Using wscc
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. wscc will pass command-line options and other files directly to cc. Following is a command that would build the addtwo application using wscc.
wscc addtwo.tm addtwo.c -o addtwo
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.
There are two basic types of WSTP program, epitomized by the addtwo and factor programs. The first is an installable program. An installable program provides new functionality to the kernel by linking a C program to the kernel through a calling mechanism. In order to get this new functionality, the user of the Wolfram Language must run the Install[] function. With the addtwo example, you will be adding a new function called AddTwo[] that adds two numbers (provided as arguments). The kernel and installable programs have a special relationship that allows them to communicate only with one another. When an installable program is run, it requires that you provide some information in order for it to connect. The other type of program is a front end. Front ends do all of the work of creating and managing their own links. In addition to the factor example, the Wolfram System front end and the Wolfram Language kernel are also examples of the front end type. A front end does not require any extra information in order to run, but it will usually make a connection at some point during its execution.
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. 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 like 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);
}
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.)
Install[] called 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:
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.
After a moment, a prompt will appear requesting that you type an integer. Type an integer with fewer than 10 digits and press the Enter key. (The other factor examples relax the restriction on the size of integer you may type in.)
The prime factors returned by the Wolfram Language are printed and factor closes its link with the Wolfram Language.
Supported Link Protocols
The C function WSOpenArgcArgv() and the Wolfram Language function LinkOpen[] are documented in "WSTP and External Program Communication". On Linux machines, the legal values for the LinkProtocol option are "TCPIP", "TCP", "SharedMemory", "Pipes", and "IntraProcess". A LinkProtocol is the mechanism used to transport data from one end of a connection to the other. "SharedMemory" is the default protocol for all LinkMode->Launch links. "SharedMemory" is the default protocol for all 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 WSOpenArgcArgv() and LinkOpen[].
- Turn off compiler optimization until your program is working. This makes compiling faster, debugging easier, and, besides, the optimizer may be broken and the cause of some problems. (Optimized code uses the stack and registers differently than unoptimized code in such a way that may expose or mask a bug in your code. For example, the common mistake of returning a pointer to a local variable may or may not cause a problem depending on stack and register use.)
- Check the return values from the WSTP library functions or call WSError() at key points in your program. WSTP will often be able to tell you what has gone wrong.
- The files wstp.h, libWSTP32i4.a, and libWSTP32i4.so (libWSTP64i4.* on 64-bit platforms) are a matched set. If you have used an earlier release of WSTP, you should take care that you do not mix components when building your application.
- Check whether the C compiler you are using supports prototypes. If it does not, you will need to change your code and the way you build your project. This is explained in the section "Building WSTP Programs".