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 librarylib
and assign the result toresultSymbol
. By default, the dynamic library name is taken from the library given toInitializePacletLibrary
(Paclet Library). A caveat is that if Paclet Library has been lazily initialized andPacletFunctionSet
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 functionlib
- 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 loadedfResultType
- result type
- LazyPacletFunctionSet[resultSymbol_, lib_, f_, fParams_, fResultType_, opts___]
Lazy version of
PacletFunctionSet
which loads the function upon the first evaluation ofresultSymbol
.- WSTPFunctionSet[resultSymbol_, lib_, f_, opts___]
A convenient wrapper around
PacletFunctionSet
for easier loading of WSTP functions. Argument and result type are fixed asLinkObject
.- LazyWSTPFunctionSet[resultSymbol_, lib_, f_, opts___]
Lazy version of
WSTPFunctionSet
which loads the function upon the first evaluation ofresultSymbol
.- MemberFunctionSet[exprHead_][memberSymbol_?Developer`SymbolQ, lib_, f_, fParams_, retType_, opts___]
Loads a library function into
memberSymbol
that can be invoked on instances ofexprHead
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 ofmemberSymbol
.- 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 ofmemberSymbol
.
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 librarylib
and return it. UnlikePacletFunctionSet
, there is no mechanism by which to avoid eager loading of the default paclet library (i.e. there is no LazyPacletFunctionLoad). Iflib
is omitted, the dynamic library name is taken from the library given toInitializePacletLibrary
.
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
-
LIBRARY_LINK_FUNCTION
(name) π 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.
Public Functions
-
MArgumentManager
(mint Argc, MArgument *Args, MArgument &Res) π Constructor.
- Parameters
[in] Argc
: - number of MArguments provided[in] Args
: - MArguments provided[in] Res
: - reference to output MArgument
-
MArgumentManager
(WolframLibraryData ld, mint Argc, MArgument *Args, MArgument &Res) π Constructor.
- Parameters
[in] ld
: - library data[in] Argc
: - number of MArguments provided[in] Args
: - MArguments provided[in] Res
: - reference to output MArgument
-
bool
getBoolean
(size_type index) const π Get MArgument of type mbool at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MArgument of type bool at position
index
-
double
getReal
(size_type index) const π Get MArgument of type mreal at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MArgument of type double at position
index
-
template<typename
T
>
TgetInteger
(size_type index) const π Get MArgument of type mint at position
index
with extra static_cast if needed.- Template Parameters
T
: - integral type to convert mint to
- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MArgument value at position
index
converted to T
-
std::complex<double>
getComplex
(size_type index) const π Get MArgument of type mcomplex at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MArgument value at position
index
converted to std::complex<double>
-
char *
getCString
(size_type index) const π Get value of MArgument of type βUTF8Stringβ at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
LLErrorCode::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
C-string which was received from LibraryLink
- Note
MArgumentManager is responsible for disowning string arguments. Do not call free() or delete() on resulting pointer.
-
std::string
getString
(size_type index) const π Get value of MArgument of type βUTF8Stringβ at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
LLErrorCode::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
std::string which is created from MArgument at position
index
-
template<typename
T
, PassingMode
= Passing::Automatic>
NumericArray<T>getNumericArray
(size_type index) const π Get MArgument of type MNumericArray at position
index
and wrap it into NumericArray.- Template Parameters
T
: - type of data stored in NumericArray
- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
NumericArray wrapper of MArgument at position
index
- See
NumericArray<T>::NumericArray(const MNumericArray);
-
template<Passing
Mode
= Passing::Automatic>
GenericNumericArraygetGenericNumericArray
(size_type index) const π Get MArgument of type MNumericArray at position
index
and wrap it into generic MContainer wrapper.- Template Parameters
Mode
: - passing mode to be used
- Parameters
index
: - position of desired MArgument inArgs
- Return
MContainer wrapper of MNumericArray with given passing mode
-
MNumericArray
getMNumericArray
(size_type index) const π Get MArgument of type MNumericArray at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Use of this function is discouraged. Use getNumericArray instead, if possible.
- Return
MArgument at position
index
interpreted as MNumericArray
-
template<typename
T
, PassingMode
= 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>
GenericTensorgetGenericTensor
(size_type index) const π Get MArgument of type MTensor at position
index
and wrap it into generic MContainer wrapper.- Template Parameters
Mode
: - passing mode to be used
- Parameters
index
: - position of desired MArgument inArgs
- Return
MContainer wrapper of MTensor with given passing mode
-
MTensor
getMTensor
(size_type index) const π Get MArgument of type MTensor at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Use of this function is discouraged. Use getTensor instead, if possible.
- Return
MTensor of MArgument at position
index
-
template<typename
T
, PassingMode
= Passing::Automatic>
SparseArray<T>getSparseArray
(size_type index) const π Get MArgument of type MSparseArray at position
index
and wrap it into SparseArray.- Template Parameters
T
: - type of data stored in SparseArray
- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
SparseArray wrapper of MArgument at position
index
-
template<Passing
Mode
= Passing::Automatic>
GenericSparseArraygetGenericSparseArray
(size_type index) const π Get MArgument of type MSparseArray at position
index
and wrap it into generic MContainer wrapper.- Template Parameters
Mode
: - passing mode to be used
- Parameters
index
: - position of desired MArgument inArgs
- Return
MContainer wrapper of MSparseArray with given passing mode
-
MSparseArray
getMSparseArray
(size_type index) const π Get MArgument of type MSparseArray at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Use of this function is discouraged. Use getSparseArray instead, if possible.
- Return
MArgument at position
index
interpreted as MSparseArray
-
template<typename
T
, PassingMode
= 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>
GenericImagegetGenericImage
(size_type index) const π Get MArgument of type MImage at position
index
and wrap it into generic MContainer wrapper.- Template Parameters
Mode
: - passing mode to be used
- Parameters
index
: - position of desired MArgument inArgs
- Return
MContainer wrapper of MImage with given passing mode
-
MImage
getMImage
(size_type index) const π Get MArgument of type MImage at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Use of this function is discouraged. Use getImage instead, if possible.
- Return
MImage of MArgument at position
index
-
template<typename
T
, PassingMode
= Passing::Automatic>
DataList<T>getDataList
(size_type index) const π Get DataStore with all nodes of the same type from MArgument at position
index
.- Template Parameters
T
: - type of data stored in each node of DataStore, it T is MArgumentType::MArgument it will accept any node
- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
DataList wrapper of MArgument at position
index
- See
DataList<T>::DataList(DataStore ds);
-
template<Passing
Mode
= Passing::Automatic>
GenericDataListgetGenericDataList
(size_type index) const π Get MArgument of type DataStore at position
index
and wrap it into generic MContainer wrapper.- Template Parameters
Mode
: - passing mode to be used
- Parameters
index
: - position of desired MArgument inArgs
- Return
MContainer wrapper of DataStore with given passing mode
-
DataStore
getDataStore
(size_type index) const π Get MArgument of type DataStore at position
index
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Use of this function is discouraged. Use getDataList instead.
- Return
DataStore of MArgument at position
index
-
template<class
ManagedExpr
, classDynamicType
= 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.
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 Parameters
T
: - any type, for types not supported by default developers may specialize this function template
- Parameters
index
: - position of desired argument inArgs
- Return
a value of type T created from the specified input argument
-
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 Parameters
ArgTypes
: - types that determine how each extracted argument will be returned
- Return
a tuple of function arguments
-
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.
- Template Parameters
ArgTypes
: - types that determine how each extracted argument will be returned
- Parameters
indices
: - position of desired arguments, need not be sorted, may contain repeated values
- Return
a tuple of function arguments
-
void
setBoolean
(bool result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - boolean value to be returned to LibraryLink
-
void
setReal
(double result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - value of type double to be returned to LibraryLink
-
void
setInteger
(mint result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - value of type mint to be returned to LibraryLink
- Warning
result
will be implicitly casted to mint with no overflow check
-
template<typename
T
>
boolsetMintAndCheck
(T result) noexcept π Set
result
as output MArgument and check for overflow.- Template Parameters
T
: - integral type to be casted to mint
- Parameters
[in] result
: - value to be returned to LibraryLink
- Return
true iff overflow occurred and the value had to be clipped
-
void
setComplex
(std::complex<double> c) noexcept π Set
c
as output MArgument.- Parameters
[in] c
: - value of type std::complex<double> to be returned to LibraryLink
-
void
setString
(const std::string &str) π Set
str
as output MArgument.- Parameters
[in] str
: - reference to std::string to be returned to LibraryLink
-
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
>
voidsetNumericArray
(const NumericArray<T> &na) π Set MNumericArray wrapped by
na
as output MArgument.- Template Parameters
T
: - NumericArray data type
- Parameters
[in] na
: - reference to NumericArray which should pass its internal MNumericArray to LibraryLink
-
void
setMNumericArray
(MNumericArray na) π Set MNumericArray as output MArgument.
- Parameters
[in] na
: - MNumericArray to be passed to LibraryLink
-
template<typename
T
>
voidsetTensor
(const Tensor<T> &ten) π Set MTensor wrapped by
ten
as output MArgument.
-
void
setMTensor
(MTensor t) π Set MTensor as output MArgument.
- Parameters
[in] t
: - MTensor to be passed to LibraryLink
-
template<typename
T
>
voidsetImage
(const Image<T> &im) π Set MImage wrapped by
im
as output MArgument.
-
void
setMImage
(MImage im) π Set MImage as output MArgument.
- Parameters
[in] im
: - MImage to be passed to LibraryLink
-
template<typename
T
>
voidsetDataList
(const DataList<T> &ds) π Set DataStore wrapped in DataList
ds
as output MArgument.- Template Parameters
T
: - type of data stored in each node of DataStore
- Parameters
[in] ds
: - const reference to DataList which should pass its internal DataStore to LibraryLink
-
void
setDataStore
(DataStore ds) π Set DataStore as output MArgument.
- Parameters
[in] ds
: - DataStore to be passed to LibraryLink
-
template<typename
T
>
voidsetSparseArray
(const SparseArray<T> &sa) π Set MSparseArray wrapped by
sa
as output MArgument.- Template Parameters
T
: - SparseArray data type
- Parameters
[in] sa
: - reference to SparseArray which should pass its internal MSparseArray to LibraryLink
-
void
setMSparseArray
(MSparseArray sa) π Set MSparseArray as output MArgument.
- Parameters
[in] sa
: - MSparseArray to be passed to LibraryLink
-
void
set
(bool result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - boolean value to be returned to LibraryLink
-
void
set
(double result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - value of type double to be returned to LibraryLink
-
void
set
(mint result) noexcept π Set
result
as output MArgument.- Parameters
[in] result
: - value of type mint to be returned to LibraryLink
- Warning
result
will be implicitly casted to mint with no overflow check
-
void
set
(std::complex<double> c) noexcept π Set
c
as output MArgument.- Parameters
[in] c
: - value of type std::complex<double> to be returned to LibraryLink
-
void
set
(const std::string &str) π Set
str
as output MArgument.- Parameters
[in] str
: - reference to std::string to be returned to LibraryLink
-
void
set
(const char *str) π Set
str
as output MArgument.- Parameters
[in] str
: - reference to std::string to be returned to LibraryLink
-
void
set
(std::string &&str) π Set
str
as output MArgument.- Parameters
[in] str
: - reference to std::string to be returned to LibraryLink
-
template<typename
T
>
voidset
(const NumericArray<T> &na) π Set MNumericArray wrapped by
na
as output MArgument.- Template Parameters
T
: - NumericArray data type
- Parameters
[in] na
: - reference to NumericArray which should pass its internal MNumericArray to LibraryLink
-
void
set
(const GenericNumericArray &na) π Set MNumericArray wrapped by
na
as output MArgument.- Parameters
[in] na
: - reference to generic NumericArray which should pass its internal MNumericArray to LibraryLink
-
template<typename
T
>
voidset
(const SparseArray<T> &ten) π Set MSparseArray wrapped by
sa
as output MArgument.- Template Parameters
T
: - SparseArray data type
- Parameters
[in] sa
: - reference to SparseArray which should pass its internal MSparseArray to LibraryLink
-
void
set
(const GenericSparseArray &t) π Set MSparseArray wrapped by
t
as output MArgument.- Parameters
[in] t
: - reference to generic SparseArray which should pass its internal MSparseArray to LibraryLink
-
template<typename
T
>
voidset
(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.- Parameters
[in] t
: - reference to generic Tensor which should pass its internal MTensor to LibraryLink
-
void
set
(const GenericImage &im) π Set MImage wrapped by
im
as output MArgument.- Parameters
[in] im
: - reference to generic Image which should pass its internal MImage to LibraryLink
-
template<typename
T
>
voidset
(const DataList<T> &ds) π Set DataStore wrapped in DataList
ds
as output MArgument.- Template Parameters
T
: - type of data stored in each node of DataStore
- Parameters
[in] ds
: - const reference to DataList which should pass its internal DataStore to LibraryLink
-
void
set
(const GenericDataList &ds) π Set DataStore wrapped by
ds
as output MArgument.- Parameters
[in] ds
: - reference to generic DataStore which should pass its internal DataStore to LibraryLink
-
template<typename
T
>
voidset
(const T &arg) π Set given value as a result of the library function.
- Template Parameters
T
: - any type, for types not supported by default developers are encouraged to specialize this function template
-
ProgressMonitor
getProgressMonitor
(double step = ProgressMonitor::getDefaultStep()) const π Get ProgressMonitor shared with WL Kernel.
- Parameters
step
: - step value for progress monitor
- Return
A new instance of ProgressMonitor class.
- Warning
If you havenβt specified βProgressMonitorβ option when loading the library function with PacletFunctionSet, then the behavior of
getProgressMonitor
is undefined.
-
numericarray_data_t
getNumericArrayType
(size_type index) const π Get type of MNumericArray at position
index
inArgs
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MNumericArray type
-
template<Passing
Mode
, classOperator
, class ...OpArgs
>
voidoperateOnNumericArray
(size_type index, OpArgs&&... opArgs) π Perform operation on NumericArray created from MNumericArray argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the NumericArray that will be processedOperator
: - any callable classOpArgs...
: - types of arguments ofoperator()
in classOperator
- Parameters
[in] index
: - position of MNumericArray inArgs
[in] opArgs
: - arguments of Operator::operator()
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Warning
Operator::operator() has to be a template that takes a const NumericArray<T>& as first argument
-
template<Passing
Mode
= Passing::Automatic, classOperator
>
voidoperateOnNumericArray
(size_type index, Operator &&op) π Perform operation on NumericArray created from MNumericArray argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the NumericArray that will be processedOperator
: - any callable class
- Parameters
[in] index
: - position of MNumericArray inArgs
[in] op
: - callable object (possibly lambda) that takes only one argument - a NumericArray
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
-
unsigned char
getTensorType
(size_type index) const π Get type of MTensor at position
index
inArgs
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MTensor type
-
template<Passing
Mode
, classOperator
, class ...Args
>
voidoperateOnTensor
(size_type index, Args&&... opArgs) π Perform operation on Tensor created from MTensor argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the Tensor that will be processedOperator
: - any callable classOpArgs...
: - types of arguments ofoperator()
in classOperator
- Parameters
[in] index
: - position of MTensor inArgs
[in] opArgs
: - arguments of Operator::operator()
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-boundsErrorName::MArgumentTensorError
: - if MTensor argument has incorrect type
- Warning
Operator::operator() has to be a template that takes a const Tensor<T>& as first argument
-
template<Passing
Mode
= Passing::Automatic, classOperator
>
voidoperateOnTensor
(size_type index, Operator &&op) π Perform operation on Tensor created from MTensor argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the Tensor that will be processedOperator
: - any callable class
- Parameters
[in] index
: - position of MTensor inArgs
[in] op
: - callable object (possibly lambda) that takes only one argument - a Tensor
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-boundsErrorName::MArgumentTensorError
: - if MTensor argument has incorrect type
-
imagedata_t
getImageType
(size_type index) const π Get type of MImage at position
index
inArgs
.- Parameters
[in] index
: - position of desired MArgument inArgs
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-bounds
- Return
MImage type
-
template<Passing
Mode
, classOperator
, class ...Args
>
voidoperateOnImage
(size_type index, Args&&... opArgs) π Perform operation on Image created from MImage argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the Image that will be processedOperator
: - any callable classOpArgs...
: - types of arguments ofoperator()
in classOperator
- Parameters
[in] index
: - position of MImage inArgs
[in] opArgs
: - arguments of Operator::operator()
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-boundsErrorName::MArgumentImageError
: - if MImage argument has incorrect type
- Warning
Operator::operator() has to be a template that takes a const Image<T>& as first argument
-
template<Passing
Mode
= Passing::Automatic, classOperator
>
voidoperateOnImage
(size_type index, Operator &&op) π Perform operation on Image created from MImage argument at position
index
inArgs
.- Template Parameters
Mode
: - passing mode of the Image that will be processedOperator
: - any callable class
- Parameters
[in] index
: - position of MImage inArgs
[in] op
: - callable object (possibly lambda) that takes only one argument - an Image
- Exceptions
ErrorName::MArgumentIndexError
: - ifindex
is out-of-boundsErrorName::MArgumentImageError
: - if MImage argument has incorrect type
-
template<typename
T
>
structCustomType
π 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
>
structGetter
π 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.
- Parameters
mngr
: - an instance of MArgumentManagerfirstIndex
: - index of the first library function parameter to be used
- Return
an object of type
T
constructed from library function arguments stored inmngr
-
template<class
Container
, PassingMode
>
structManaged
π 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
>
structSetter
π 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.
-
using