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
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
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
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"]
Compile MathLink Programs
Compile MathLink Programs
The C compiler driver detects that a MathLink template file is used and calls mprep before using the output as input to the C compiler.
Needs["CCompilerDriver`"]
files = FileNames["*",
FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links",
"MathLink", "DeveloperKit", $SystemID, "MathLinkExamples",
"addtwo"}]];
prog = CreateExecutable[files, "addTwo"]
Install[prog]
is linked with the object. The following calls the computation:
AddTwo[2, 3]
In this case we get the number "5" as the result.
Supported C Compilers
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
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" -> "
"CompilerName" -> "tcc"]
Import["!\"" <> greeter <> "\"", "Text"]
A Small Example
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]