Skip to content
njpipeorgan edited this page Feb 19, 2020 · 4 revisions

Wolfram LibraryLink provides users a way to call external programs in Wolfram Language (Mathematica). The external binary codes are loaded into the Wolfram Kernel through dynamic libraries (.dll, .so). Therefore, compared to WSTP, the overhead of calling a function using LibraryLink is much lower, and argument passing is much more efficient. Wolfram LibraryLink User Guide gives a comprehend description of LibraryLink.

Although LibraryLink makes it possible to improve runtime efficiency, it comes at the cost of writing tedious boilerplate code, in addition to writing functions in C/C++. wll-interface is a header only library written in C++, which simplifies LibraryLink coding and make it less error-prone.

Two examples

Load a C++ function into Mathematica

We start with a C++ function multiply:

double multiply(double x, int y)
{
    return x * y;
}

We use wll-interface to simplify the process of loading this function — just add two lines of code:

src = "
#include \"wll_interface.h\"  // include the header file

double multiply(double x, int y)
{
    return x * y;
}

DEFINE_WLL_FUNCTION(multiply)  // defines wll_multiply
";

Now we create a shared library from the code. You need to replace <path-to-wll_interface.h> below with the directory that contains the header file wll_interface.h so that the compiler can find it.

Needs["CCompilerDriver`"];
mylib = CreateLibrary[src, "wll_multiply"(* name of the library, can be anything *), 
  "IncludeDirectories" -> {"<path-to-wll_interface.h>"}, 
  Language -> "C++", "CompileOptions" -> "-std=c++17"]

Finally, we load the function into Mathematica, and use it. Note that the function we loaded is called wll_multiply. wll-interface add wll_ in front of the C++ function and define the new function according to LibraryLink specifications.

multiply = LibraryFunctionLoad[mylib, "wll_multiply", {Real, Integer}, Real];
multiply[2.33, 5]

Call an external function

Calling external library often involves the representations of data structures. wll-interface abstracts the data structures in LibraryLink by classes or native types. See Type Specification for more information.

In this example, we are going to load std::sort in C++ STL into Mathematica.

src = "
#include <algorithm>
#include "wll_interface.h"

wll::list<double> sort(wll::list<double> a)
{
    std::sort(a.begin(), a.end());
    return a;
}
DEFINE_WLL_FUNCTION(sort)
";

MTensor in LibraryLink is represented in wll-interface as wll::tensor<Type, Rank>, and wll::list<double> is an alias for wll::tensor<double, 1>. begin and end are member functions of wll::tensor class that return iterators.

Then we create a library from the code

Needs["CCompilerDriver`"];
mylib = CreateLibrary[src, "wll_sort"(* name of the library, can be anything *), 
  "IncludeDirectories" -> {"<path-to-wll_interface.h>"}, 
  Language -> "C++", "CompileOptions" -> "-std=c++17",
  "Libraries" -> {}, 
  "LibraryDirectories" -> {}
]

"Libraries" and "LibraryDirectories" can be used to specify dependencies on external libraries. Since std::sort is compiled with the function sort, we do not need to specify any dependency.

Finally, we load the function into Mathematica, and use it.

sort = LibraryFunctionLoad[mylib, "wll_sort", {{Real, 1}}, {Real, 1}];
sort[{5., 4., 3., 2., 1.}]