C-Integration Grundgedanke: Starte einen C-Compiler aus/mit Mathematica, kompiliere den Code und verbinde diesen mit Mathematica. Weitere Anwendungen: Benutze in Mathematica anstatt dem internen Mathematica-Compiler einen externen C-Compiler Integriere C-Programme in Mathematica und nutze diese als normale Mathematica-Funktionen Integriere C-Programme in Mathematica und parallelisiere diese mit Mathematica Baue eigenständige C-Programme aus Mathematica .exe, .lib oder .obj Verteilen von selbst geschriebener Software MathLink Programme kompilieren C-Compiler Ein kleines Beispiel Erstellen von Software Erstellen einer Executable Executables lassen sich mit vielen verschiedenen C-Compilern auf verschiedenen Rechnerarchitekturen erstellen. Mit folgendem Mathematica Code lässt sich das bewerkstelligen. Needs["CCompilerDriver`"]CreateExecutable[" #include <stdio.h> int main(){printf(\"hello world\\n\");}", "hello"] Erstellen einer Library-Datei Wie bei einer ausführbaren Datei lassen sich Library-Dateien mit vielen Compilern auf verschiedenen Plattformen generieren. Needs["CCompilerDriver`"]file = FileNameJoin[ {$CCompilerDirectory, "SystemFiles", "CSource", "createDLL_demo.c"}];CreateLibrary[{file}, "demoLibrary"] Erstellen einer Object-Datei Die Object-Dateien lassen sich als Eingabe für CreateExeceutable oder CreateLibrary benutzen. Needs["CCompilerDriver`"] file = FileNameJoin[ {$CCompilerDirectory, "SystemFiles", "CSource", "createDLL_demo.c"}];CreateObjectFile[{file}, "demoLibrary"] Verteilen von selbst geschriebener Software Kunden dürfen die mit Mathmatica generierten Executables im Rahmen der Lizenzbedingungen frei verteilen, wobei die jeweilige Lizenzierungsklasse (Industrie, Lehre, Behörde, Schule, Student, Home Edition) eingehalten werden muss. Ein Student darf also keine Programme für die Industrie erstellen ohne eine Industrie-Lizenz zu besitzen. Wie üblich dürfen die benutzen Libraries nicht verändert oder rückentwickelt "reverse engineered" werden. Da es sich hier um eine lizenzrechtliche Angelegenheit handelt, hier der Originaltext: Computer code generated by the user in Mathematica may require certain Mathematica components to be included with the code package in order to run. These Mathematica components, listed below, may be redistributed with the code package. Using these included components in any way other than to distribute and run the program code is expressly prohibited. WolframRTL.dll WolframRTL.lib WolframRTL_Minimal.dll WolframRTL_Minimal.lib WolframRTL_Static_Minimal.lib libWolframRTL.so libWolframRTL_Minimal.so libWolframRTL_Static_Minimal.a libWolframRTL.dylib libWolframRTL_Minimal.dylib MathLink-Programme kompilieren Der Treiber des C-Compilers erkennt, dass ein MathLink Template benutzt wird und ruft mprep auf, bevor die Ausgabe als Eingabe für den C-Compiler überreicht wird. Needs["CCompilerDriver`"]files = FileNames["*", FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links", "MathLink", "DeveloperKit", $SystemID, "MathLinkExamples", "addtwo"}]];prog = CreateExecutable[files, "addTwo"] Mit Install[prog] wird das Objekt gelinkt, und folgender Aufruf führt nun die Berechnung durch: AddTwo[2, 3] In diesem Fall erhalten wir als Ergebnis die Zahl "5". C-Compiler Unterstützte C-Compiler Unterstützte C-Compiler Windows: Visual Studio Express 2008, 2010 Visual Studio Professional 2005, 2008, 2010 Cygwin 1.7.5 mit 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 Aufruf von C-Compilern Der Aufruf von C-Compilern ist auch möglich. Im Folgenden finden Sie ein kleines Beispiel, in dem der TinyCC benutzt wird. Hierfür gibt es allerdings keinen Support. Needs["CCompilerDriver`"] Needs["CCompilerDriver`GenericCCompiler`"] greeter = CreateExecutable[" #include <stdio.h> int main() { printf(\"Hello TinyCC world.\\n\"); }", "hiworld", "Compiler" -> GenericCCompiler, "CompilerInstallation" -> "/Pfad/zum/C-Compiler", "CompilerName" -> "tcc"] Import["!\"" <> greeter <> "\"", "Text"] Ein kleines Beispiel Sie können - wie hier in dem Beispiel zu sehen ist - sehr schnell "standalone" Applikationen erstellen. Hier wird ein RC-Tiefpassfilter erstellt, der Signale in Textform entgegen nimmt und das Ausgangssignal erzeugt. Als erstes definieren wir unsere Tiefpass-Funktion. 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]}]]]; Nun wird der C-Code und der Header erstellt. targetDir = CreateDirectory[]fnSource = FileNameJoin[{targetDir, "lopass.c"}];Export[fnSource, lopass]; Dann wird eine C-Main-Funktion geschrieben, um den generierten Code aufzurufen. lopassmainSrcFile = FileNameJoin[{targetDir, "lopassMain.c"}];Export[lopassmainSrcFile, lopassmainSrc, "Text"] Danach wird mit der Wolfram Runtime Library kompiliert, um eine ausführbare Datei zu erstellen. Needs["CCompilerDriver`"];lopassExe = CreateExecutable[{fnSource, lopassmainSrcFile}, "lowpass", "TargetDirectory" -> targetDir, "Libraries" -> "WolframRTL_Static_Minimal"] Nun können Sie Ihre Datei weiterverteilen und außerhalb von Mathematica nutzen. Sie können die Datei allerdings auch aus Mathematica selbst aufrufen, um sie zu testen oder vorzuführen. Wir erstellen nun ein Eingangssignal. input = Table[Sin[x] + Sin[x*10] + Sin[x*50], {x, 0, 10, 0.01}];ListPlot[input, Joined -> True] Eine Textdatei wird aus unserem Signal erstellt. 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"] Die ausführbare Datei wird gestartet, das Ausgabesignal konvertiert und unser Eingangs- (blau) und Ausgangssignal (rot) in einem Plot gezeichnet. 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]