# MathLink to C++ member function

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.

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.

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

typedef struct bola bola;

bola* newBola();
double bola_getSurface(bola* b);
void deleteBola(bola* b);

#ifdef __cplusplus
}
#endif
#endif


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();}
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));

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


And the C function:

// (*This file is surfaceBolaM.c *)
#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];
./surfaceBolaM
In[2]:= (surfaceBolaM[2.55555]/4/Pi)^.5
Out[2]= 2.55555
Out[3]="./surfaceBolaM"


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

// (*bola.h*)
#ifndef BOLA_H
#define BOLA_H
class bola{
private:
public:
double getSurface();
~bola(){}
};
#endif

// (*bola.cpp*)
#include <cmath>
#include "bola.h"

• The required compiler options are explained here. -luuid is needed only from Mathematica 10.0 onwards. I don't think -m64 -fPIC  are needed. – Szabolcs May 25 '16 at 17:45
• Also, extern "C" should only be needed for the prototype (declaration), not for the definition of the functions. – Szabolcs May 25 '16 at 17:48