Gluing external functions in the interpreter |
In order to glue C++ functions in the
Write mmx files which define the correspondance
between the
Generate cpp files from the mmx files using autoglue, to define the glue functions.
Compile the generated cpp files to build the dynamic library to be loaded in the interpretor.
The mmx files for the correspondance between the
mathemagix functions and the external functions in the
require "basix/glue_double.mmx";
foreign cpp import {
cpp_include "my_fct.hpp";
f : Double -> Double == my_fct;
}
In this example, the function f of the interpretor
uses the
double my_fct(double)
declared in the file my_fct.hpp.
A important rule to keep in mind is the following:
The glue of a function is generated iff the types in its signature are specialized.
In our example, the inclusion of the file basix/glue_double.mmx defines the required specialization for the type Double, so that the fonction f will be defined.
Here is a second example:
foreign cpp import {
cpp_preamble /"
using namespace std;
inline double make_tropical(double x) {return x;}
"/;
class Tropical == double;
tropical : Tropical -> Tropical == make_tropical;
infix +: (Tropical, Tropical) -> Tropical == max;
infix *: (Tropical, Tropical) -> Tropical == infix +;
}
specialize Tropical;
We define a new type Tropical in the interpretor,
which is implemented in C++ as double. We define a
function tropical which corresponds to the C++
function make_tropical and operators +
corresponding to max and *
corresponding to the C++ operator +. The function make_tropical is defined in the preamble part which will
copied verbatim in the generated glue file. The specialize
instruction is needed to generate the glue for all these functions.
These functions can be used in the
a: Tropical := tropical(2.2);
b: Tropical := tropical(0.1);
a+b;
a*b;
In the next example, we glue template functions:
include "basix/categories.mmx
require "basix/glue_int.mmx";
require "basix/glue_double.mmx";
foreign cpp import {
cpp_preamble /"using namespace std;"/;
cpp_include "dual_number.hpp";
forall(C: Class) {
class Dual C == pair C;
dual : (C,C) -> Dual C == pair C;
}
forall(C: Ring) {
infix +: (Dual C, Dual C) -> Dual C == dual_add;
infix *: (Dual C, Dual C) -> Dual C == dual_mul ;
}
forall(C: Field) {
infix /: (Dual C, Dual C) -> Dual C == dual_div ;
}
}
specialize Dual Int;
specialize Dual Double;
In this example, the parameterised type Dual C of dual numbers is implemented as std::pair<C>. The constructor dual is valid for any type of coefficients C, but the operators + and * are glued only if C is a ring (here for Int and Double) whereas the link of the operator / is valid is C is a field (here for Double). The glue of these functions is generated throught the instructions specialize Dual Int; specialize Dual Double;
Supose that the name of the package is pkg. By convention, the glue files which provide specialization should be put in the folder pkg/glue. Then running
mmxglue
in the folder pkg will generate the corresponding cpp glue files in the folder pkg/glue. The CMakeLists.txt will be uptable. To generate the dynamic library which can be uploaded in the interpretor, the following command can be run:
cmake ../pkg -DGLUE=ON && make
The library libmmxpkg(.so,.dyl) will be compiled in the local folder lib and can be loaded with
use "tropical";