Library functions ๐Ÿ”—

By library function (also LibraryLink function) we understand a C++ function with one of the following signatures

EXTERN_C DLLEXPORT int f (WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res);

or

EXTERN_C DLLEXPORT int f (WolframLibraryData libData, WSLINK wslp);

Such functions are building blocks of every LibraryLink paclet. They are usually called directly from the Wolfram Language after being loaded from the dynamic library first. It is common for paclets to also define functions entirely in the Wolfram Language or provide thin Wolfram Language wrappers around loaded library functions for instance in order to validate input data and then pass it down to the C++ code.

Function arguments ๐Ÿ”—

Passing data between Wolfram Language and external C or C++ libraries is a core feature of LibraryLink. This is far from a straightforward task, because in the Wolfram Language everything is an expression and variableโ€™s type can change at run time, whereas C and C++ variables are statically typed. Apart from that, every C/C++ library may define custom data types it uses.

LibraryLink does the heavy lifting by providing translation between popular Wolfram Language expression types and corresponding C types. For instance, when you pass a String expression to the library function, you will receive a null-terminated char* in the C code, or passing a NumericArray will yield an object of type MNumericArray.

In practice, what you will receive in a library function as input arguments from the Wolfram Language is an array of MArgument, which is a union type:

typedef union {
        mbool *boolean;
        mint *integer;
        mreal *real;
        mcomplex *cmplex;
        MTensor *tensor;
        MSparseArray *sparse;
        MNumericArray *numeric;
        MImage *image;
        char **utf8string;
} MArgument;

Similarly, there is one MArgument to store the result of your library function that you want to return to the Wolfram Language. You must also remember that some types of arguments need special treatment, for example you must call UTF8String_disown on string arguments to avoid memory leaks.

Developers who are not familiar with this part of LibraryLink are encouraged to consult the official guide before reading on.

LLU hides all those implementation details in the MArgumentManager class. You still need to know what the actual argument types are but you can now extract arguments using member functions like getInteger, getString etc. and set the resulting value with set without worrying about memory management.

Example ๐Ÿ”—

Write a library function that adds two integers. First thing you need to do is to create an instance of MArgumentManager initialized with all arguments to the library function:

EXTERN_C DLLEXPORT int AddTwoIntegers(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    LLU::MArgumentManager mngr {libData, Argc, Args, Res};
    auto n1 = mngr.get<mint>(0);  // get first (index = 0) argument, which is of type mint
    auto n2 = mngr.get<mint>(1);  // get second argument which is also an integer

    mngr.set(n1 + n2);  // set the sum of arguments to be the result
    return LLU::ErrorCode::NoError;
}

Such function, when compiled into a shared library, say myLib.so, could be loaded into WolframLanguage and used like this:

AddInts = LibraryFunctionLoad["myLib", "AddTwoIntegers", {Integer, Integer}, Integer];

AddInts[17, 25]
(* = 42 *)

Loading library functions ๐Ÿ”—

In the example above we saw how library functions can be loaded from shared objects via LibraryFunctionLoad:

FunctionNameInWL = LibraryFunctionLoad["path/to/sharedLibrary", "FunctionNameInCppCode", {ArgumentType1, ArgumentType2, ...}, ResultType];

The syntax is described in details in LibraryLink ยป Functions, Arguments, and Results.

In case of WSTP library functions, the call gets simplified to:

FunctionNameInWL = LibraryFunctionLoad["path/to/sharedLibrary", "FunctionNameInCppCode", LinkObject, LinkObject];

It is common but not in any way required to have FunctionNameInWL be equal to FunctionNameInCppCode with a $ prepended, e.g.

$FunctionName = LibraryFunctionLoad["path/to/sharedLibrary", "FunctionName", LinkObject, LinkObject]

LLU expands the library loading mechanism in LibraryLink by providing convenient wrappers with extra options:

SafeLibraryLoad[lib_]

Quietly attempts to load the dynamic library lib, and throws if it cannot be loaded.

PacletFunctionSet[resultSymbol_, lib_, f_, fParams_, fResultType_, opts___]

Attempts to load an exported function f from a dynamic library lib and assign the result to resultSymbol. By default, the dynamic library name is taken from the library given to InitializePacletLibrary (Paclet Library). A caveat is that if Paclet Library has been lazily initialized and PacletFunctionSet is called with a path to it, then auto-loading of Paclet Library will not be triggered. By default, the name of the library function is assumed to be the same as the symbol name (sans any leading or trailing $โ€™s).

Arguments:
  • resultSymbol - a WL symbol to represent the loaded function

  • lib - name of the dynamic library [optional]

  • f - name of the function to load from the dynamic library [optional]

  • fParams - parameter types of the library function to be loaded

  • fResultType - result type

LazyPacletFunctionSet[resultSymbol_, lib_, f_, fParams_, fResultType_, opts___]

Lazy version of PacletFunctionSet which loads the function upon the first evaluation of resultSymbol.

WSTPFunctionSet[resultSymbol_, lib_, f_, opts___]

A convenient wrapper around PacletFunctionSet for easier loading of WSTP functions. Argument and result type are fixed as LinkObject.

LazyWSTPFunctionSet[resultSymbol_, lib_, f_, opts___]

Lazy version of WSTPFunctionSet which loads the function upon the first evaluation of resultSymbol.

MemberFunctionSet[exprHead_][memberSymbol_?Developer`SymbolQ, lib_, f_, fParams_, retType_, opts___]

Loads a library function into memberSymbol that can be invoked on instances of exprHead like so: instance @ memberSymbol[โ€ฆ]

LazyMemberFunctionSet[exprHead_][memberSymbol_?Developer`SymbolQ, lib_, f_, fParams_, retType_, opts___]

Lazy version of MemberFunctionSet which loads the function upon the first evaluation of memberSymbol.

WSTPMemberFunctionSet[exprHead_][memberSymbol_, lib_, f_, opts___]

A convenient wrapper around MemberFunctionSet for easier loading of WSTP member functions.

LazyWSTPMemberFunctionSet[exprHead_][memberSymbol_, lib_, f_, opts___]

Lazy version of WSTPMemberFunctionSet which loads the function upon the first evaluation of memberSymbol.

There is also one lower level function which does not take a symbol as first argument but instead returns the loaded library function as the result

PacletFunctionLoad[lib_, f_, fParams_, retType_, opts___]

Attempts to load an exported function f from a dynamic library lib and return it. Unlike PacletFunctionSet, there is no mechanism by which to avoid eager loading of the default paclet library (i.e. there is no LazyPacletFunctionLoad). If lib is omitted, the dynamic library name is taken from the library given to InitializePacletLibrary.

Supported options for all of the above functions include:

"Optional" -> True | False ๐Ÿ”—

Whether the library function is optional in the library, i.e. loading may fail quietly. Defaults to False.

"ProgressMonitor" -> None | _Symbol ๐Ÿ”—

Provide a symbol which will store the current progress of library function. See Progress monitor for details. Defaults to None.

"Throws" -> True | False ๐Ÿ”—

Whether the library function should throw Failure expressions on error or return them as the result. Defaults to True (so Failures will be thrown).

Reducing boilerplate code ๐Ÿ”—

The set of utility functions described in the previous section allows you to reduce the amount of code you need to write in order to load functions from your pacletโ€™s dynamic library to the Wolfram Language. Similarly, LLU provides a number of macros that eliminate the need to repeat the full signature for every library function.

After you include <LLU/LibraryLinkFunctionMacro.h> instead of writing:

EXTERN_C DLLEXPORT int name (WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res);

you can type

This macro forward declares and begins the definition of an extern โ€œCโ€ LibraryLink function with given name.

For input parameter and return type explanation see the official LibraryLink guide. WolframLibraryData parameter is marked [[maybe_unused]] because it is a common workflow to take the instance of WolframLibraryData passed to WolframLibrary_initialize function and store it with LLU::LibraryData::setLibraryData so that it is accessible everywhere. With such setup one does not need to use the WolframLibraryData copy provided to every LibraryLink function.

And similarly instead of

EXTERN_C DLLEXPORT int name (WolframLibraryData libData, WSLINK wslp);

you can use

LIBRARY_WSTP_FUNCTION(name) ๐Ÿ”—

This macro forward declares and begins the definition of an extern โ€œCโ€ LibraryLink function with given name, which uses WSTP to exchange data with WolframLanguage.

For input parameter and return type explanation see the official LibraryLink guide. WolframLibraryData parameter is marked [[maybe_unused]] because it is a common workflow to take the instance of WolframLibraryData passed to WolframLibrary_initialize function and store it with LLU::LibraryData::setLibraryData so that it is accessible everywhere. With such setup one does not need to use the WolframLibraryData copy provided to every LibraryLink function.

Finally, if you use exception-based error handling you will often end up writing code like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
EXTERN_C DLLEXPORT int name(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    auto err = ErrorCode::NoError;
    try {
        LLU::MArgumentManager mngr {libData, Argc, Args, Res};
        // body of a function that effectively takes mngr as the single parameter
    } catch (const LibraryLinkError& e) {
        err = e.which();
    } catch (...) {
        err = ErrorCode::FunctionError;
    }
    return err;
}

Fortunately, there is a macro that allows you to focus only on the highlighted part:

LLU_LIBRARY_FUNCTION(name) ๐Ÿ”—

This macro provides all the boilerplate code needed for a typical exception-safe LibraryLink function.

LLU_LIBRARY_FUNCTION(MyFunction) defines a LibraryLink function MyFunction and a regular function impl_MyFunction of type void(LLU::MArgumentManager&), which is the one you need to provide a body for. All LLU::LibraryLinkError exceptions thrown from impl_MyFunction will be caught and the error code returned to LibraryLink. All other exceptions will also be caught and translated to a FunctionError.

Note

While this macro saves quite a lot of typing it may also decrease code readability and make debugging harder so use with caution.

User-defined types ๐Ÿ”—

LibraryLink supports a number of types as function arguments and for the majority of use cases the built-in types are enough. However, imagine you are writing a library that operates on financial data and it processes amounts of money. For example, in the Wolfram Language you work with expressions like Quantity[20.3, "USD"] and in C++ you have a corresponding structure:

struct Money {
    double amount;
    std::string currency;
};

If you want to write a library function that takes an amount of money and a currency and converts that amount to the given currency, you will probably choose {Real, String, String} for argument types (Quantity would be split into Real and String and the second String is for the new currency) and "DataStore" for the return type. This requires some extra code on the Wolfram Language side to extract Real and String from the Quantity and on the C++ side to construct a DataStore from a Money object. Having large number of functions in the library that may repeat those translations, you will probably decide to factor this extra code to helper functions.

You could then use your library in Wolfram Language as follows:

(* Load raw library function that operates on basic LibraryLink types *)
$ConvertMoney = LibraryFunctionLoad["myLib.so", "ConvertMoney", {Real, String, String}, "DataStore"];

(* Create a higher-level wrapper for users of your package *)
ConvertMoney[amount_Quantity, newCurrency_String] := With[
   {
      rawlibraryResult = $ConvertMoney[QuantityMagnitude[amount], QuantityUnit[amount], newCurrency];
   },
   $dataStoreToQuantity[rawLibraryResult]  (* $dataStoreToQuantity is a small utility function, omitted for brevity *)
];

ConvertMoney[Quantity[50., "USD"], "PLN"]
(* = Quantity[XXX, "PLN"] *)

The implementation of ConvertMoney in C++ would go along the lines:

EXTERN_C DLLEXPORT int ConvertMoney(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    LLU::MArgumentManager mngr {libData, Argc, Args, Res};
    auto amount = mngr.get<double>(0);
    auto oldCurrency = mngr.get<std::string>(1);
    auto newCurrency = mngr.get<std::string>(2);

    auto moneyToConvert = Money { amount, oldCurrency };
    Money converted = myLib::convert(moneyToConvert, newCurrency);

    mngr.set(myLib::MoneyToDataList(converted));  // myLib::MoneyToDataList is a helper function to convert Money object to a DataList
    return LLU::ErrorCode::NoError;
}

This is a fine code and if you are satisfied with it, you can stop reading here. However, it is possible with LLU to implement the same functionality like this:

(* Load "ConvertMoney" function from "myLib.so" and assign it to ConvertMoney symbol *)
`LLU`PacletFunctionSet[ConvertMoney, "myLib.so", "ConvertMoney", {"Money", String}, "Money"];

(* No need for separate higher-level wrapper because the types are translated by LLU now. *)

ConvertMoney[Quantity[50., "USD"], "PLN"]
(* = Quantity[XXX, "PLN"] *)

and in C++

EXTERN_C DLLEXPORT int ConvertMoney(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    LLU::MArgumentManager mngr {libData, Argc, Args, Res};
    auto moneyToConvert = mngr.get<Money>(0);
    auto newCurrency = mngr.get<std::string>(2);  // under the hood Money object is still sent as two values (Real + String), so new currency has index 2

    Money converted = myLib::convert(moneyToConvert, newCurrency);

    mngr.set(converted);
    return LLU::ErrorCode::NoError;
}

The point is to delegate the translation between your types and LibraryLink types to LLU, so that you can write cleaner code that does not distract readers with technicalities. To achieve this, you need to teach LLU to understand your types. Here is how you register "Money" as a library function argument type, the values of which are of the form Quantity[_Real, _String]:

`LLU`MArgumentType["Money", {Real, String}, (Sequence[QuantityMagnitude[#], QuantityUnit[#]]) &];

The second argument is the list of basic LibraryLink types that constitute to a single expression of type "Money". The third argument is a translation function that takes something of the form Quantity[_Real, _String] and produces a Sequence of two values: Real and String.

In the C++ code we used mngr.get<Money>, which means we have to tell LLU how many and what basic LibraryLink types correspond to a Money object. This is achieved by defining a specialization of CustomType structure template and providing a type alias member CorrespondingTypes which must be a std::tuple of corresponding basic LibraryLink types:

template<>
struct LLU::MArgumentManager::CustomType<Money> {
   using CorrespondingTypes = std::tuple<double, std::string>;
};

With this information, whenever LLU is requested to read an argument of type Money it will read two consecutive input arguments as double and std::string, respectively, and construct a Money object from those 2 values.

In many cases this is sufficient, however in some situations you may want to have full control over how LLU creates objects of your type. Imagine we want to always capitalize the currency that is passed from Wolfram Language code, before creating a Money object. To have such fine-grained control over MArgumentManagerโ€™s behavior, we must additionally specialize a struct template Getter that provides a member function get, like this:

template<>
struct LLU::MArgumentManager::Getter<Money> {
   static Money get(const MArgumentManager& mngr, size_type index) {
      auto [amount, currency] = mngr.getTuple<double, std::string>(index);
      std::transform(currency.begin(), currency.end(), currency.begin(), [](unsigned char c){ return std::toupper(c); });
      return Money { amount, std::move(currency) };
   }
};

At this point, LLU knows how to change WL expressions of the form Quantity[_Real, _String] into Money objects in C++. The only thing left is to teach LLU how to work in the other direction, i.e. how to return Money objects via โ€œDataStoreโ€ and change them into Quantity. First, let us specialize MArgumentManager::set template:

template<>
void LLU::MArgumentManager::set<Money>(const Money& m) const {
    DataList<NodeType::Any> moneyDS;
    moneyDS.push_back(m.amount);
    moneyDS.push_back(m.currency);
    set(moneyDS);
}

You can read more about DataList in the section about Containers. The last step is to tell LLU how to turn incoming DataStores into Quantities in library functions that declare โ€œMoneyโ€ as return type:

`LLU`MResultType["Money", "DataStore", (Quantity @@ #)&];

Here we say that if a library function has return type โ€œMoneyโ€, then the corresponding LibraryLink type is โ€œDataStoreโ€ and when we get such a DataStore we need to apply a function (Quantity @@ #)& to turn it into the form that we use to represent Money expressions.

Registering user-defined types in LLU may seem like a lot of extra work, but actually it is no extra work at all. It is merely a way to organize the code that you would previously have written anyway in the form of small utility functions scattered all over your library and possibly even duplicated, if you are not careful enough.

API reference ๐Ÿ”—

class LLU::MArgumentManager ๐Ÿ”—

Manages arguments exchanged between the paclet C++ code and LibraryLink interface.

MArgumentManager provides a safe way to access MArguments received from LibraryLink and takes care of memory management both for in- and out- arguments. Using MArgumentManager one can perform generic operations on NumericArrays, Tensors and Images independent of their data type.

Public Types

using size_type = std::size_t ๐Ÿ”—

Size type for indexing the list of arguments that MArgumentManager manages.

template<typename T>
using RequestedType = typename RequestedTypeImpl<T>::type ๐Ÿ”—

RequestedType<T> is usually just T and is used as return type of MArgumentManager::get(size_type)

Public Functions

MArgumentManager(mint Argc, MArgument *Args, MArgument &Res) ๐Ÿ”—โ–ผ

Constructor.

MArgumentManager(WolframLibraryData ld, mint Argc, MArgument *Args, MArgument &Res) ๐Ÿ”—โ–ผ

Constructor.

bool getBoolean(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type mbool at position index.

double getReal(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type mreal at position index.

template<typename T>
T getInteger(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type mint at position index with extra static_cast if needed.

std::complex<double> getComplex(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type mcomplex at position index.

char *getCString(size_type index) const ๐Ÿ”—โ–ผ

Get value of MArgument of type โ€œUTF8Stringโ€ at position index.

std::string getString(size_type index) const ๐Ÿ”—โ–ผ

Get value of MArgument of type โ€œUTF8Stringโ€ at position index.

template<typename T, Passing Mode = Passing::Automatic>
NumericArray<T> getNumericArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MNumericArray at position index and wrap it into NumericArray.

template<Passing Mode = Passing::Automatic>
GenericNumericArray getGenericNumericArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MNumericArray at position index and wrap it into generic MContainer wrapper.

MNumericArray getMNumericArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MNumericArray at position index.

template<typename T, Passing Mode = Passing::Automatic>
Tensor<T> getTensor(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MTensor at position index and wrap it into Tensor object.

template<Passing Mode = Passing::Automatic>
GenericTensor getGenericTensor(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MTensor at position index and wrap it into generic MContainer wrapper.

MTensor getMTensor(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MTensor at position index.

template<typename T, Passing Mode = Passing::Automatic>
SparseArray<T> getSparseArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MSparseArray at position index and wrap it into SparseArray.

template<Passing Mode = Passing::Automatic>
GenericSparseArray getGenericSparseArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MSparseArray at position index and wrap it into generic MContainer wrapper.

MSparseArray getMSparseArray(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MSparseArray at position index.

template<typename T, Passing Mode = Passing::Automatic>
Image<T> getImage(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MImage at position index and wrap it into Image object.

template<Passing Mode = Passing::Automatic>
GenericImage getGenericImage(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MImage at position index and wrap it into generic MContainer wrapper.

MImage getMImage(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type MImage at position index.

template<typename T, Passing Mode = Passing::Automatic>
DataList<T> getDataList(size_type index) const ๐Ÿ”—โ–ผ

Get DataStore with all nodes of the same type from MArgument at position index.

template<Passing Mode = Passing::Automatic>
GenericDataList getGenericDataList(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type DataStore at position index and wrap it into generic MContainer wrapper.

DataStore getDataStore(size_type index) const ๐Ÿ”—โ–ผ

Get MArgument of type DataStore at position index.

template<class ManagedExpr, class DynamicType = ManagedExpr>
DynamicType &getManagedExpression(size_type index, ManagedExpressionStore<ManagedExpr> &store) const ๐Ÿ”—โ–ผ

Get a reference to an instance of Managed Expression that was sent from Wolfram Language as argument to a library function.

template<class ManagedExpr, class DynamicType = ManagedExpr>
std::shared_ptr<DynamicType> getManagedExpressionPtr(size_type index, ManagedExpressionStore<ManagedExpr> &store) const ๐Ÿ”—โ–ผ

Get a shared pointer to an instance of Managed Expression that was sent from Wolfram Language as argument to a library function.

template<typename T>
RequestedType<T> get(size_type index) const ๐Ÿ”—โ–ผ

Extract library function argument at given index and convert it from MArgument to a desired type.

template<typename ...ArgTypes>
std::tuple<RequestedType<ArgTypes>...> getTuple(size_type index = 0) const ๐Ÿ”—โ–ผ

Extract arguments from the Manager and return them as values of given types.

template<typename ...ArgTypes>
std::tuple<RequestedType<ArgTypes>...> getTuple(std::array<size_type, sizeof...(ArgTypes)> indices) const ๐Ÿ”—โ–ผ

Extract arguments from the Manager at given positions and return them as values of given types.

void setBoolean(bool result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

void setReal(double result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

void setInteger(mint result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

template<typename T>
bool setMintAndCheck(T result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument and check for overflow.

void setComplex(std::complex<double> c) noexcept ๐Ÿ”—โ–ผ

Set c as output MArgument.

void setString(const std::string &str) ๐Ÿ”—โ–ผ

Set str as output MArgument.

void setString(const char *str) ๐Ÿ”—

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

void setString(std::string &&str) ๐Ÿ”—

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<typename T>
void setNumericArray(const NumericArray<T> &na) ๐Ÿ”—โ–ผ

Set MNumericArray wrapped by na as output MArgument.

void setMNumericArray(MNumericArray na) ๐Ÿ”—โ–ผ

Set MNumericArray as output MArgument.

template<typename T>
void setTensor(const Tensor<T> &ten) ๐Ÿ”—โ–ผ

Set MTensor wrapped by ten as output MArgument.

void setMTensor(MTensor t) ๐Ÿ”—โ–ผ

Set MTensor as output MArgument.

template<typename T>
void setImage(const Image<T> &im) ๐Ÿ”—โ–ผ

Set MImage wrapped by im as output MArgument.

void setMImage(MImage im) ๐Ÿ”—โ–ผ

Set MImage as output MArgument.

template<typename T>
void setDataList(const DataList<T> &ds) ๐Ÿ”—โ–ผ

Set DataStore wrapped in DataList ds as output MArgument.

void setDataStore(DataStore ds) ๐Ÿ”—โ–ผ

Set DataStore as output MArgument.

template<typename T>
void setSparseArray(const SparseArray<T> &sa) ๐Ÿ”—โ–ผ

Set MSparseArray wrapped by sa as output MArgument.

void setMSparseArray(MSparseArray sa) ๐Ÿ”—โ–ผ

Set MSparseArray as output MArgument.

void set(bool result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

void set(double result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

void set(mint result) noexcept ๐Ÿ”—โ–ผ

Set result as output MArgument.

void set(std::complex<double> c) noexcept ๐Ÿ”—โ–ผ

Set c as output MArgument.

void set(const std::string &str) ๐Ÿ”—โ–ผ

Set str as output MArgument.

void set(const char *str) ๐Ÿ”—โ–ผ

Set str as output MArgument.

void set(std::string &&str) ๐Ÿ”—โ–ผ

Set str as output MArgument.

template<typename T>
void set(const NumericArray<T> &na) ๐Ÿ”—โ–ผ

Set MNumericArray wrapped by na as output MArgument.

void set(const GenericNumericArray &na) ๐Ÿ”—โ–ผ

Set MNumericArray wrapped by na as output MArgument.

template<typename T>
void set(const SparseArray<T> &ten) ๐Ÿ”—โ–ผ

Set MSparseArray wrapped by sa as output MArgument.

void set(const GenericSparseArray &t) ๐Ÿ”—โ–ผ

Set MSparseArray wrapped by t as output MArgument.

template<typename T>
void set(const Tensor<T> &ten) ๐Ÿ”—โ–ผ

Set MTensor wrapped by ten as output MArgument.

void set(const GenericTensor &t) ๐Ÿ”—โ–ผ

Set MTensor wrapped by t as output MArgument.

template<typename T>
void set(const Image<T> &im) ๐Ÿ”—โ–ผ

Set MImage wrapped by im as output MArgument.

void set(const GenericImage &im) ๐Ÿ”—โ–ผ

Set MImage wrapped by im as output MArgument.

template<typename T>
void set(const DataList<T> &ds) ๐Ÿ”—โ–ผ

Set DataStore wrapped in DataList ds as output MArgument.

void set(const GenericDataList &ds) ๐Ÿ”—โ–ผ

Set DataStore wrapped by ds as output MArgument.

template<typename T>
void set(const T &arg) ๐Ÿ”—โ–ผ

Set given value as a result of the library function.

ProgressMonitor getProgressMonitor(double step = ProgressMonitor::getDefaultStep()) const ๐Ÿ”—โ–ผ

Get ProgressMonitor shared with WL Kernel.

numericarray_data_t getNumericArrayType(size_type index) const ๐Ÿ”—โ–ผ

Get type of MNumericArray at position index in Args.

template<Passing Mode, class Operator, class ...OpArgs>
void operateOnNumericArray(size_type index, OpArgs&&... opArgs) ๐Ÿ”—โ–ผ

Perform operation on NumericArray created from MNumericArray argument at position index in Args.

template<Passing Mode = Passing::Automatic, class Operator>
void operateOnNumericArray(size_type index, Operator &&op) ๐Ÿ”—โ–ผ

Perform operation on NumericArray created from MNumericArray argument at position index in Args.

unsigned char getTensorType(size_type index) const ๐Ÿ”—โ–ผ

Get type of MTensor at position index in Args.

template<Passing Mode, class Operator, class ...Args>
void operateOnTensor(size_type index, Args&&... opArgs) ๐Ÿ”—โ–ผ

Perform operation on Tensor created from MTensor argument at position index in Args.

template<Passing Mode = Passing::Automatic, class Operator>
void operateOnTensor(size_type index, Operator &&op) ๐Ÿ”—โ–ผ

Perform operation on Tensor created from MTensor argument at position index in Args.

imagedata_t getImageType(size_type index) const ๐Ÿ”—โ–ผ

Get type of MImage at position index in Args.

template<Passing Mode, class Operator, class ...Args>
void operateOnImage(size_type index, Args&&... opArgs) ๐Ÿ”—โ–ผ

Perform operation on Image created from MImage argument at position index in Args.

template<Passing Mode = Passing::Automatic, class Operator>
void operateOnImage(size_type index, Operator &&op) ๐Ÿ”—โ–ผ

Perform operation on Image created from MImage argument at position index in Args.

template<typename T>
struct CustomType ๐Ÿ”—

Helper structure that can be used to register user-defined argument types in LLU.

If you want a type X to be supported as template argument for MArgumentManager::get<>, you must specialize CustomType<> for X and this specialization must contain a type alias CorrespondingTypes which is defined to be a std::tuple of basic LibraryLink types, from which an object of type X can be constructed. See online docs and MArgumentManager unit tests for examples.

Template Parameters
  • T: - any type you would like to treat as a user-defined LibraryLink argument type

template<typename T>
struct Getter ๐Ÿ”—

Helper structure to fully customize the way MArgumentManager reads T as argument type.

If T is a user-defined argument type, LLU will by default attempt to create an object of type T by reading values of corresponding types and feeding it to a constructor of T. Specialize Getter<> to override this behavior.

Template Parameters
  • T: - any type, for which you would like full control over how MArgumentManager reads arguments of that type

Note

Every user-defined argument type must specialize CustomType<>, specializing Getter<> is optional.

Public Static Functions

T get(const MArgumentManager &mngr, size_type firstIndex) ๐Ÿ”—โ–ผ

A function that tells LLU how to interpret an object of a user-defined type as an argument of a library function This function is used internally by MArgumentManager::get.

template<class Container, Passing Mode>
struct Managed ๐Ÿ”—

Helper struct to โ€œattachโ€ a passing mode to container type when passing it as template argument to MArgumentManager::getTuple.

Template Parameters
  • Container: - any generic or strongly typed container wrapper type (e.g. GenericImage, Tensor<mint>, etc.)

  • Mode: - passing mode for the container

template<typename T>
struct Setter ๐Ÿ”—

Helper structure to fully customize the way MArgumentManager sets an object of type T as result of a library function.

Note

You can explicitly specialize MArgumentManager::set for your type T, but having Setter<> allows you to define partial specializations.

Public Static Functions

void set(MArgumentManager&, const T&) ๐Ÿ”—

A function that tells LLU how to send an object of a user-defined type as a result of a library function This function is used internally by MArgumentManager::set.