The task is to compile, link and install in Mathematica (9.0, Linux 64 bit) some functions defined in C++. These functions are defined within classes. I have access to the header which forward define the classes, but I would like not to touch the C++ code that properly defines what these functions do.


1 Answer 1


First approach is to create C wrappers for the C++ code. The very simple example I work below defines a class "bola" which represents a sphere with a radius. The member function gives the surface. So, the forward definition (C++ style) of the class functions is in "bola.h" and the definitions of the functions are in "bola.cpp". I give the code for these two at the end. We could assume that these two files have been compiled before and maybe we only have access to the compiled object.

The wrapper header:

// (*This file is bola_cWrap.h*)
#ifndef BOLA_H
#define BOLA_H
#ifdef __cplusplus
extern "C" {

typedef struct bola bola;

bola* newBola();
void bola_setRadius(bola* b, double radius);
double bola_getSurface(bola* b);
void deleteBola(bola* b);

#ifdef __cplusplus

And the definitions of these wrap functions :

// (*This file is bola_cWrap.cpp*)
#include "bola.h"
#include "bola_cWrap.h"
extern "C" {
  bola* newBola(){return new bola();}
  void bola_setRadius(bola* b, double radius){b->setRadius(radius);}
  double bola_getSurface(bola* b){return(b->getSurface());}
  void deleteBola(bola* b){delete b;}


The template of the link between Mathematica and the 'surface' function:

::  // (*This is surfaceBolaM.tm*)
void surfaceBolaM P(( double x));

:Function:       surfaceBolaM
:Pattern:        surfaceBolaM[x_Real]
:Arguments:      { x }
:ArgumentTypes:  { Real}
:ReturnType:     Manual

And the C function:

// (*This file is surfaceBolaM.c *)
#include "mathlink.h"
#include "bola_cWrap.h"

 void surfaceBolaM(double r);
 void surfaceBolaM(double r){
 struct bola* negra=newBola();
 double s=bola_getSurface(negra);
int main(int argc, char* argv[])
  return MLMain(argc, argv);

I have not being able to link and create the executable files from the CCompilerDriver package functions within Mathematica. But I obtained the needed libraries and include directories from its CreateExecutable function using the option "ShellCommandFunction" :> Print . After that, I can build from the shell (or maybe using Run).

> g++ -Wall -c bola_cWrap.cpp
> ./mprep -o surfaceBolaMtm.c surfaceBolaM.tm
> gcc -Wall -c  -m64 -fPIC -O2 -I "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/IncludeFiles/C" -I "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions"  surfaceBolaMtm.c surfaceBolaM.c -L"$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions" -L "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Libraries/Linux-x86-64" -l"ML64i3" -lm -lpthread -lrt -lstdc++
> g++ -Wall -I "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/IncludeFiles/C" -I "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions" surfaceBolaMtm.o surfaceBolaM.o bola_cWrap.o bola.o -o surfaceBolaM -L"$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions" -L "$MATH_INSTALL_DIR/Wolfram/Mathematica/9.0/SystemFiles/Libraries/Linux-x86-64" -l"ML64i3" -lm -lpthread -lrt -lstdc++

And it creates the executable "surfaceBolaM". I am sure I am parsing some options to the g++ compiler which do not make much sense, but it did not complain.

Finally, you can install the executable in Mathematica

In[1]:=Clear[link]; link =Install["surfaceBolaM"]; Print[link];
In[2]:= (surfaceBolaM[2.55555]/4/Pi)^.5
Out[2]= 2.55555

Just in case, here are the sources for "bola.cpp" and "bola.h"

// (*bola.h*)
#ifndef BOLA_H
#define BOLA_H
class bola{
 double m_radius;
 void setRadius(double radius);
 double getSurface();

// (*bola.cpp*)
#include <cmath>
#include "bola.h"
void bola::setRadius(double radius){m_radius=radius;}
double bola::getSurface(){return(12.5664*pow(m_radius,2));}

I have suffered with this. I am kind of annoyed by the Mathematica documentation which refers in many places to "C/C++" stuff when it is not quite the same. It was quite an additional effort to learn the C++ details after learning the mathlink integration with C, specially for people (like me) not familiar with any of these two languages.

  • 2
    $\begingroup$ The required compiler options are explained here. -luuid is needed only from Mathematica 10.0 onwards. I don't think -m64 -fPIC are needed. $\endgroup$
    – Szabolcs
    May 25, 2016 at 17:45
  • $\begingroup$ Also, extern "C" should only be needed for the prototype (declaration), not for the definition of the functions. $\endgroup$
    – Szabolcs
    May 25, 2016 at 17:48
  • $\begingroup$ @Szabolcs It did not link at the end without that extern C in "bola_cWrap.cpp" $\endgroup$
    – user13427
    May 25, 2016 at 17:53
  • $\begingroup$ The extern in "surfaceBolaM.c" apparently is not needed. $\endgroup$
    – user13427
    May 25, 2016 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.