17
$\begingroup$

We are developing a quite large mathematical software in C++ and would like to have a Mathematica interface. We have our own C++ library and our idea would be, to write a Mathematica wrapper class and call functions from that library.

We looked into "MathLink" and "LibraryLink" for quite some amount of time now and still cannot figure out, how to properly write the interface. Currently, our biggest struggle is how to wrap our classes to Mathematica usable code (like PyObject in Python -- we have a Python interface as well). It seems like "MathLink" does not do the job (How can I wrap a C++ object in WSTP?) So we looked into LibraryLink. But the official documentation is either too complex or too simple.

To make our question concrete: We have a dynamic library, with some individual classes, and we would like to construct instances of these classes in our interface and call library functions on them. Is that possible? And if so, how? And in particular, with the least amount of effort?

$\endgroup$
3
  • $\begingroup$ It sounds like my LTemplate package will be great for you. It is much easier (and especially faster) to use than pure LibraryLink. But I am not sure if it is easier to learn. I suppose it is, but I always tell people that they should at least understand plain LibraryLink before starting to use LTemplate. I based IGraph/M on LTemplate. It has ~2000 lines of C++ I wrote, plus 6000 lines of interface code that LTemplate generates for me. $\endgroup$
    – Szabolcs
    Apr 20, 2017 at 10:38
  • $\begingroup$ If you want, you can email me to discuss if LTemplate is useful for your project. $\endgroup$
    – Szabolcs
    Apr 20, 2017 at 10:48
  • $\begingroup$ Well, have you come to a decision about what interface to use? Did you take a look at LTemplate? $\endgroup$
    – Szabolcs
    Apr 24, 2017 at 15:42

1 Answer 1

14
$\begingroup$

This cannot be answered very well without knowing your C++ library much better.

As you said, you have a choice between MathLink and LibraryLink. Generally, I recommend LibraryLink because:

  • It runs in the same process, and data transfer is much faster than with MathLink
  • It provides features that MathLink does not have, such as direct manipulation of packed arrays, managed library expressions, fast callback functions
  • You can use MathLink for communication in LibraryLink functions when you need it

MathLink is not really an extension API. It is a communication protocol which works either within a single process, between two processes (typical way), or even through the network.

The two main advantages of extending Mathematica through installable MathLink programs (instead of LibraryLink):

  • Easier to get started because much of the interface code is generated for you by the mprep utility from .tm template files. See tutorial.

  • Your code will run in a separate process, and will communicate with Mathematica through the MathLink protocol. If your code crashes, it won't take down the whole Mathematica kernel. (This is what happens when it crashes.)

I use LibraryLink a lot myself, and created the LTemplate package to make it just as easy to use as MathLink template files:

Just like mprep, this package will generate much of the interface code from a "template" (this time given as a Mathematica expression).

A big difference from MathLink template files is that LTemplate relies on C++ heavily (C is not sufficient), and the templates describe an interface to a C++ class. Thus you must work with classes. On the upside, it automates creating managed library expressions, which in plain term means that you won't have to delete your objects explicitly from Mathematica—it will be done for you when there are no more references to them.

So far it sounds like a perfect match for your project, and I do recommend that you should check it out.

But be aware that:

  • You will not be able to just write a template for your existing C++ classes (unless they are trivial). You will need to create a wrapper class that is appropriate for LTemplate and uses its types (which correspond to Mathematica's types)

  • You really should not expose a class interface to your users in Mathematica. Mathematica is not Python, and it does not like mutable state. I strongly recommend to hide the fact that you are using classes in the background, and write a simpler function interface that avoids mutable state completely. This is what I do in my IGraph/M package, which is based on LTemplate. When I write something for my own private use, I often leave the classes exposed because I know how to use them. But doing this will likely confuse many Mathematica users, who are not used to this. (To be fair, I should point out that Mathematica ships with some packages which expose such an interface, and require manual object management: TriangleLink and TetGenLink.)

LTemplate is still a work in progress. Since I did not get a lot of feedback about it, I only worked on features I needed myself. It currently supports integer, real and complex dense and sparse arrays, as well as the typical scalar types (boolean, string, number). It's what most math-focused libraries need. It also lets you use MathLink-based communication when you need it.

RawArray support is in the works, and will be ready soon. RawArray is an undocumented type that you probably don't need. Support for Image (MImage type) and better integration with C++ templates is also in the works, but this won't be ready anytime soon.

$\endgroup$
4
  • $\begingroup$ Hey! Thanks for your detailed answer. I think we will use your plugin. But first of all we need to changer our program in the following way: we have like 30 different data types and each has its own getter and setter. So first, we will write four, five getters for the different output types (like matrix, vector, integer, bool...). Then we will use these for our wrapper class. $\endgroup$
    – Richard
    Apr 26, 2017 at 7:56
  • $\begingroup$ One more question: We have a major class ("cone") and it has all these properties and data types. If I understand you correctly, you recommend to hide this class from the user. But we also do not want to compute things over and over again. Is there a nice way around? Like writing a new class inside the Mathematica language? $\endgroup$
    – Richard
    Apr 26, 2017 at 8:05
  • $\begingroup$ @Richard If you are going to use LTemplate, it is really the best if you send me an email, so I can be aware of what you are doing and make sure it will work for you. Then I can answer your questions in more detail than is possible in a comment. $\endgroup$
    – Szabolcs
    Apr 26, 2017 at 8:24
  • $\begingroup$ @Richard You don't have to hide the classes from the user. If you don't, using the interface will require a bit more attention, but there are already packages like this. Take a look at how TriangleLink and TetGenLink work. $\endgroup$
    – Szabolcs
    Apr 27, 2017 at 8:08

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.