Neu in Mathematica 8 – C-Integration

Integrated C Workflow

Basica idea: Start a C compiler from/with Mathematica, compile the code, and link it with Mathematica.
Other applications:

  • Use an external C compiler in Mathematica instead of the internal Mathematica compiler
  • Integrate C code in Mathematica and use it as normal Mathematica functions
  • Integrate C code in Mathematica and parallelize it with Mathematica
  • Generate standalone C code from Mathematica

Create Executable Files

Executables can be created from many different C compilers running on different architectures. You can do that by using the following Mathematica Code.

Needs["CCompilerDriver`"]
CreateExecutable["
#include

int main(){
printf(\"hello world\\n\");
}
", "hello"]

Create Library Files

Like an executable file, Library files can be created from many different compilers running on different platforms.

Needs["CCompilerDriver`"]
file = FileNameJoin[ {$CCompilerDirectory, "SystemFiles", "CSource",
"createDLL_demo.c"}];
CreateLibrary[{file}, "demoLibrary"]

Create Object Files

The object files can be used as input to CreateExeceutable or CreateLibrary.

Needs["CCompilerDriver`"]
file = FileNameJoin[ {$CCompilerDirectory, "SystemFiles", "CSource",
"createDLL_demo.c"}];
CreateObjectFile[{file}, "demoLibrary"]

Supported C Compilers

Supported C Compilers
Windows: Visual Studio Express 2008, 2010 Visual Studio Professional 2005, 2008, 2010 Cygwin 1.7.5 with GCC 3.4 MinGW 5.1.6
Windows-x86-64: Visual Studio Express 2008, 2010 Visual Studio Professional 2005, 2008, 2010 Intel C/C++ Compiler 11.1
Linux: GCC 4.0
Linux-x86-64: GCC 4.0 Intel C/C++ Compiler 11.1
MacOSX-x86: GCC 4.0
MacOSX-x86-64: GCC 4.0 Intel C/C++ Compiler 11.1

Unsupported C Compilers

Calling unsupported C compilers is also possible. Below, you will find a small example, in which TinyCC is used.

Needs["CCompilerDriver`"]

Needs["CCompilerDriver`GenericCCompiler`"]

greeter = CreateExecutable["
#include
int main() {
printf(\"Hello TinyCC world.\\n\");
}",
"hiworld", "Compiler" -> GenericCCompiler,
"CompilerInstallation" -> "
/path/to/ccompiler",
"CompilerName" -> "tcc"]

Import["!\"" <> greeter <> "\"", "Text"]

A Small Example

You can - as you can see in this example - create "standalone" applications very quickly. Here, an RC low pass is created, receiving signals in text form and generating the output signal.

At first, we define the low pass function.

lopass = Compile[{{x, _Real, 1}, dt, RC},
Module[{a = dt/(RC + dt), yprev = First[x], yi},
Table[yi = a*x[[i]] + (1 - a)*yprev;
yprev = yi;
yi, {i, 1, Length[x]}]]];

Now, the C code and header are generated.

targetDir = CreateDirectory[]
fnSource = FileNameJoin[{targetDir, "lopass.c"}];
Export[fnSource, lopass];

Then we write a C main function to call the generated code.

lopassmainSrcFile = FileNameJoin[{targetDir, "lopassMain.c"}];
Export[lopassmainSrcFile, lopassmainSrc, "Text"]

After that, we compile it into an executable using the Wolfram Runtime Library.

Needs["CCompilerDriver`"];
lopassExe =
CreateExecutable[{fnSource, lopassmainSrcFile}, "lowpass",
"TargetDirectory" -> targetDir,
"Libraries" -> "WolframRTL_Static_Minimal"]

Now you can distribute the program and run it outside of Mathematica. You can also run it inside Mathematica to test and demonstrate it. Set up an input signal.

input = Table[Sin[x] + Sin[x*10] + Sin[x*50], {x, 0, 10, 0.01}];
ListPlot[input, Joined -> True]

From our signal, a text file is generated.

inputText =
StringJoin[ToString[Length[input]], "\n",
Riffle[ToString /@ input, "\n"],(* dt*)"0.01",(*RC *)"0.3"];
inputFile = FileNameJoin[{targetDir, "input.txt"}];
Export[inputFile, inputText, "Text"]

The executable file is launched, the output signal is converted, and our input signal (blue) and output signal (red) are plotted.

SetDirectory[targetDir]; outputLines =
Import["!" <> lopassExe <> " < " <> inputFile, "Lines"];
ResetDirectory[];
output = ToExpression /@ outputLines;
output = If[
Length[output] > 1 && First[output] === 0 &&
output[[2]] === Length[output] - 2,
Drop[output, 2],
$Failed
];

ListPlot[{input, output}, Joined -> True]


© ADDITIVE GmbH. All rights, errors and amendments reserved.

Impressum  /  Datenschutz  /  AGB