How to Use Mathematica From ROOT ?
It is possible to invoke functions from libraries in an interactive
Root session. However, because the Mathematica libraries have not been
compiled with the compiler option Position Independent Code, it is not
possible to call these routines from a shared library. One must build a main
program or libraries with explicit references to the list of functions that one
intend to call from the interpreter.
MathematicaFunctions.h
We also define the functions startMathematica()
and stopMathematica()
which are needed in order to avoid the time-consuming restarting of the
Mathematica engine each time the function is evaluated.
MathematicaFunctions.cxx
The file MathematicaMacros.h can be downloaded
here. It contains the macro definitions
needed for Mathematica. If you ever need to generate it for your
platform you can do it the following way:
Then you might add ifdefs protecting against multiple inclusion and
commenting out the mathlink.h include because it might confuse
rootcint. In principle, you could
run the preprocessor on the file referencing the Mathematica library.
However, this is not a good practice for several reasons. One is that
your file gets heavily modified so you will need to always keep a copy
without the macro definitions and preprocess the file after every
change. Two, if you have several files referencing the Mathematica
library you will end up with multiple definitions of the same macro.
So, it is better to preprocess an empty file once for all and include
it when needed.
The file MathematicaLinkDef.h below includes the directives for
rootcint.
It declares the list of functions callable from the interpreter.
MathematicaLinkDef.h
We are now ready to generate the dictionary and interface function for
the interpreter (here called Mathematica.cxx). Execute the following
shell script
command:
rootMathematica.cxx
Examples of linking a Root application are given for your platform in ${ROOTSYS}/test/Makefile.
This example references the Mathematica software on the CERN afs cell. Please update this reference to your own installation of Mathematica.
This command invokes the C++ compiler and creates an executable module
called rootMathematica. Your path to Mathematica may vary
depending on your system. We are now ready to execute this interactive
module.
The example below shows a few commands typed in an interactive
session.
WARNING! If you use
Mathematica this way, normally the Mathematica process will be shut
down anyway when you quit ROOT. However, if you use Mathematica from a
separate wrapper or shared library, make sure that you stop Mathematica
at the end of your application as Mathematica licences might be limited
(as is the case at CERN) and restarting ROOT might create each time a
new process eating up the licences!
In the first method one directly links to the Mathematica function.
The procedure to follow is the following:1. Create files to be processed by rootcint
The file MathematicaFunctions.h below must include the list of prototypes for the functions to be called. In this example, the function callMathematicaGamma(x) is declared. Add as many such lines than you have functions.#ifndef MathematicaFunctions_H #define MathematicaFunctions_H int startMathematica(); void stopMathematica(); double callMathematicaGamma(double x); #endif // MathematicaFunctions_H
#include "/afs/cern.ch/project/parc/math50/AddOns/MathLink/DeveloperKit/Linux/CompilerAdditions/mathlink.h" #include "MathematicaMacros.h" #include <string> #include <iostream> MLINK lp; MLEnvironment env; int startMathematica() { env = MLInitialize(NULL); if (env == NULL) return 1; int argc = 4; char *argv[5] = {static_cast<char*>("-linkname"), static_cast<char*>("/afs/cern.ch/project/parc/math50/bin/math -mathlink"), static_cast<char*>("-linkmode"), static_cast<char*>("launch"), NULL}; lp = MLOpen(argc, argv); if (lp == NULL) return 1; std::cout << "Started Mathematica Engine..." << std::endl; return 0; } void stopMathematica() { MLClose(lp); MLDeinitialize(env); } double callMathematicaGamma(double x) { double result; MLPutFunction(lp, "Gamma", 1); MLPutDouble(lp, x); MLEndPacket(lp); while (MLNextPacket(lp) != RETURNPKT) MLNewPacket(lp); MLGetDouble(lp, &result); return result; }
touch MathematicaMacros.h /afs/cern.ch/project/parc/math50/AddOns/MathLink/DeveloperKit/Linux/CompilerAdditions/mprep \ -prototypes MathematicaMacros.h > MathematicaMacros.h
#ifdef __CINT__ #pragma link C++ function startMathematica(); #pragma link C++ function callMathematicaGamma(double ); #pragma link C++ function stopMathematica(); #endif
rootcint -f Mathematica.cxx -c MathematicaFunctions.h MathematicaLinkDef.h
2. Make your own main program
As an example of main program, you can copy the standard Root main program and add to it the references to the Mathematica functions as illustrated in the example below://///////////////////////////////////////////////////////////////////////// // // // RMain // // // // Main program used to create RINT application with Mathematica support // // // /////////////////////////////////////////////////////////////////////////// #include "TRint.h" #include "MathematicaFunctions.h" //_________________________________________________________________________ int main(int argc, char **argv) { if (0) { // dummy block to force the Mathematica functions to be linked by C++ callMathematicaGamma(1.0); } // Create an interactive ROOT application TRint *theApp = new TRint("Rint", &argc, argv); // and enter the event loop... theApp->Run(); delete theApp; return 0; }
3. Compile and link
Modify your Makefile to include the files above and reference the libraries. Below is an example valid on Linux with the g++ compiler.Examples of linking a Root application are given for your platform in ${ROOTSYS}/test/Makefile.
This example references the Mathematica software on the CERN afs cell. Please update this reference to your own installation of Mathematica.
g++ -I $ROOTSYS/include \ -I/afs/cern.ch/project/parc/math50/AddOns/MathLink/DeveloperKit/Linux/CompilerAdditions \ rootMathematica.cxx Mathematica.cxx MathematicaFunctions.cxx \ /afs/cern.ch/project/parc/math50/AddOns/MathLink/DeveloperKit/Linux/CompilerAdditions/libML.a \ -o rootMathematica `root-config --glibs` -lrt
./rootMathematica root [0] startMathematica() Started Mathematica Engine... (int)0 root [1] callMathematicaGamma(5.0) (double)2.40000000000000000e+01 root [2] callMathematicaGamma(5.45) (double)4.83037558000228415e+01 root [3] stopMathematica() root [4] .q