Code Generation

Code generation from Mathematica involves converting programs written in the Mathematica language into other languages and then supporting them so that they can be executed. The Mathematica compiler provides a system for code generation into the C language.

The CCodeGenerator Package

The CCodeGenerator package is a key component of code generation from Mathematica. It provides a number of functions, which are described below, that make use of the Mathematica compiler for generating C code.

CCodeGenerate[comp,fun,file]generates C code for compiled function comp, using function fun, and saves in file
CCodeStringGenerate[comp,fun]generates a string of C code for compiled function comp, using function fun
SymbolicCGenerate[comp,fun]generates SymbolicC for compiled function comp, using function fun
LibraryGenerate[comp,fun]generates a shared library for compiled function comp, using function fun

Functions provided by the CCodeGenerator package.

To use the CCodeGenerator package you have to load it.

In[1]:=
Click for copyable input

This is a compiled function to use to demonstrate code generation.

In[2]:=
Click for copyable input

The following generates a fragment of C code for the compiled function.

In[3]:=
Click for copyable input
Out[3]=

The code fragment is designed so that it could be compiled into a library; it includes generic initialization, life cycle management for this function, and the actual body of the function.

An application can call this function by importing a header file and linking against a suitable code module such as a shared library. You can also generate the header by setting the option to as shown below.

In[4]:=
Click for copyable input
Out[4]=

Generic Initialization

The initial section of a generated C includes generic C initialization. A sample is shown below.

#include "math.h"

#include "WolframRTL.h"

static WolframCompileLibrary_Functions funStructCompile;

static mbool initialize = 1;

WolframRTL.h is a header file that sets up various important definitions.

WolframCompileLibrary_Functions is a type that holds a collection of callback functions; it is an immutable object that holds no state. An instance of this, funStructCompile, is kept in the file.

initialize is an mbool variable, which is used by the specific initialization functions.

Life Cycle Management

Generated C includes a section for managing the life cycle of the code. This involves initialization and uninitialization specific to the particular function. A sample is shown below.

# include "compute.h"

DLLEXPORT int Initialize_compute (WolframLibraryData libData)
{
if ( initialize)
{
funStructCompile = libData -> compileLibraryFunctions;
initialize = 0;
}
return 0;
}

DLLEXPORT void Uninitialize_compute (WolframLibraryData libData)
{
if ( ! initialize)
{
initialize = 1;
}
}

This includes the header file, generated by setting option to ; it also includes a function to initialize the structures, Initialize_compute, and one to uninitialize any state, Uninitialize_compute. The initialization function must be called before the main function is used.

The initialize and the uninitialize functions must be called with a WolframLibraryData argument. This can be created by the loading function.

The Function

The actual body of a function is shown below. Note that the name "compute" was set in the call to GenerateCCodeString.

DLLEXPORT int compute (WolframLibraryData libData, mreal A1, mreal *Res)
{
mreal R0_0;
mreal R0_1;
mreal R0_2;
mreal R0_3;
R0_0 = A1;
R0_1 = R0_0 * R0_0;
R0_2 = sin (R0_1);
R0_3 = R0_1 + R0_2;
*Res = R0_3;
funStructCompile -> WolframLibraryData_cleanUp (libData, 1);
return 0;
}

This shows how the function arguments take the input and also the result as a pointer. The actual return value is used to indicate an error. The function is declared with DLLEXPORT, a macro defined in WolframLibrary.h. This allows the function to be exported from a Windows DLL; on non-Windows platforms the macro has an empty definition.

The function also needs a WolframLibraryData argument. This can be created by the loading function.

Working with Generated Code

Code generated by Mathematica needs various support files, which are included in the Mathematica layout. This includes header files that contain declarations for building and libraries that contain the actual code needed to support generated functions.

WolframRTL.hheader file for the Wolfram Runtime Library definitions

Header file used by generated code, found in /SystemFiles/IncludeFiles/C.

There are various runtime libraries to support the generated code for each platform.

WolframRTL.dllfull shared library for runtime support
WolframRTL.libexports for full shared library for runtime support
WolframRTL_Minimal.dllminimal shared library for runtime support
WolframRTL_Minimal.libexports for minimal shared library for runtime support
WolframRTL_Static_Minimal.libminimal static library for runtime support

Runtime library support for generated code on Windows platforms, found in /SystemFiles/Libraries/$SystemID.

libWolframRTL.sofull shared library for runtime support
libWolframRTL_Minimal.sominimal shared library for runtime support
libWolframRTL_Static_Minimal.aminimal static library for runtime support

Runtime library support for generated code on Linux platforms, found in /SystemFiles/Libraries/$SystemID.

libWolframRTL.dylibfull shared library for runtime support
libWolframRTL_Minimal.dylibminimal shared library for runtime support
libWolframRTL_Static_Minimal.aminimal static library for runtime support

Runtime library support for generated code on Macintosh platforms, found in /SystemFiles/Libraries/$SystemID.

The full runtime libraries all have a dependency on other libraries such as the Intel MKL library, which is bundled with Mathematica. This gives very fast execution speed, but it means that to use the library externally from Mathematica you have to arrange to use the MKL library.

The minimal libraries have fewer dependencies on other libraries. For example, they have no dependency on the Intel MKL library. This gives slower execution speed for computations that need to use MKL, such as matrix multiplications.

You can compile generated files using whatever tools you like. The documentation here will show how to use the Mathematica C Compiler Driver package. First, you have to load the packages.

In[1]:=
Click for copyable input

This creates a temporary directory to hold files and the resulting executable.

In[4]:=
Click for copyable input
Out[4]=

This is some sample C code to test the generated code; it is written using SymbolicC. It calls a function compute passing in an argument and receives the result, which is then printed in output.

In[5]:=
Click for copyable input
Out[6]=

Notice how the calling function creates a WolframLibraryData object; this is used for the call to the initialize function and also in the call to the compute function.

The following writes the C code to an output file.

In[7]:=
Click for copyable input
Out[7]=

Here, a compiled function is created, which is then used to generate a C file and a header file. All the output goes into the output directory created earlier.

In[10]:=
Click for copyable input

This compiles all the source files into an executable. Notice how it links in the static minimal library; this is an easy way to set up this demonstration. On a different platform you would need to use the appropriate library.

In[11]:=
Click for copyable input
Out[11]=

You can run the generated code in a shell; it will run the computation that started in the compiled function and print out the result.

You can also run the generated code from Mathematica, using Import to read the result.

In[12]:=
Click for copyable input
Out[12]=

For your own code generation purposes you might wish to link your executable to one of the other runtime libraries.

Control Expressions

You can generate C code for certain control expressions such as StateSpaceModel expressions.

In[1]:=
Click for copyable input
Out[1]=

The following makes an output directory to store the generated code.

In[2]:=
Click for copyable input
Out[2]=

Here, C code for the state space model is generated and stored in the file control.c.

In[3]:=
Click for copyable input

A header file was created as well as a C file.

In[5]:=
Click for copyable input
Out[5]=

You can compile this C code in an executable or a library with the CCompilerDriver package. First, it has to be loaded.

In[6]:=
Click for copyable input

This creates a library for the control expression.

In[7]:=
Click for copyable input
Out[7]=

The library can then be used in computations external to Mathematica.

Scope of Generated Code

This section describes the scope of Mathematica computations that can be used with the code generator.

The code generator is based on the Mathematica compiler. You must be using Compile in order to make any progress with the code generator.

However, not all inputs processed by the compiler can be turned into generated code. This includes any external calls, which call back to Mathematica. These cannot be used for code generation.

New to Mathematica? Find your learning path »
Have a question? Ask support »