5
$\begingroup$

I'm building an interface for a Fortran library. I would like to use LibraryLink and Mathematica to do the compilation (via CreateLibrary), Visual Studio is installed.

So far thing work pretty well, I can call functions and return results using the LibraryLink interface (like MArgument_getInteger() and MArgument_setReal()).

Now I'm running into problems. One function returns various numbers, a list and a string as result. A heterogenous return type is not included in the normal LL interface, but there seems to be a way using WSTP.

According to the documentation, in LibraryLink there's an argument type "LinkObject", which then uses WSTP to exchange data. The example uses WSGetString, WSPutString and so on, but neglects to mention in which header they're defined.

Since I'm using CreateLibrary to compile the C code, I can't simply add wstp.h (which exists, but is at a rather different place than WolframLibrary.h), because I'd also need to include some library to be linked.

So how do I properly use WSTP in my case?

$\endgroup$
6
$\begingroup$

You will find a complete example at:

$InstallationDirectory/SystemFiles/Links/LibraryLink/LibraryResources/Source/demo_LinkObject.c

It's good to be aware that renaming MathLink to WSTP was a capricious marketing move that brought zero technical benefits but caused quite a bit of harm to compatibility. Now the same system comes under two names, and as two incompatible libraries that use different naming conventions. However, there is no difference in capabilities.

Unless you are using the very latest version of Mathematica (or if you want your code to be compatible with slightly older versions too) use the ML-prefixed functions and mathlink.h, not the WS-prefixed one and wstp.h. Until recently, only the ML-prefixed ones worked with LibraryLink without extra tweaks, even though the renaming to WSTP was done as early as v10.0.

| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ OK, I had tried this using "wstp.h", which failed. Using "mathlink.h" does the job. Wolfram documentation is a catastrophe. Thanks a lot :) $\endgroup$ – Batox Apr 22 at 11:47
  • 2
    $\begingroup$ I strongly agree with your characterization of the documention on these matters... Btw.: Szabolcs wrote a nice package called "LTemplate`" that makes it quite easy to interact with external libraries through LibraryLink and to avoid this WSTP mess. One has to write a wrapper C++-class for that, but that class makes it also quite easy to handle multiple return values: Write the results to the class' properties and request them one by one through LibraryLink functions. $\endgroup$ – Henrik Schumacher Apr 22 at 11:54
  • $\begingroup$ @Batox I believe that in recent versions both should be usable: wstp.h with WS-prefixed functions or mathlink.h with ML-prefixed functions. I have not tried the former though. $\endgroup$ – Szabolcs Apr 22 at 14:15
  • $\begingroup$ LTemplate currenly uses the ML-prefix functions. It's particularly useful if you want to create a certain data structure on the C side and then repeatedly manipulate it in various ways. $\endgroup$ – Szabolcs Apr 22 at 14:16
  • $\begingroup$ @Szabolcs: No, I get "Cannot open include file" when I try #include "wstp.h" (Mathematica 12). The file is in some other directory than mathlink.h. $\endgroup$ – Batox Apr 23 at 11:47
0
$\begingroup$

CreateLibrary can automatically find include paths and library files of WolframLibrary and WSTP, see: https://reference.wolfram.com/language/CCompilerDriver/tutorial/Compilation.html#172287854

In particular:

In addition to the settings from "IncludeDirectories", other locations are added by default. These include the locations of include files for Wolfram Libraries and for WSTP. The actual locations are set by the option "SystemIncludeDirectories".

and

In addition to these settings, other locations and libraries are also added. These include settings so that WSTP libraries can be found. If you want to modify these standard settings you can use the options "SystemLibraryDirectories" and "SystemLibraries".

Unfortunately, this isn't 100% correct, for example:

In[1]:= CreateLibrary["#include <wstp.h>", "testLib"]

During evaluation of In[4]:= CreateLibrary::cmperr: Compile error: testLib.c(1): fatal error C1083: Cannot open include file: 'wstp.h': No such file or directory

Out[1]= $Failed

It turns out one needs to specify "TransferProtocolLibrary" option for CreateLibrary:

In[2]:= CreateLibrary["#include <wstp.h>", "testLib", "TransferProtocolLibrary" -> "WSTP"]

Out[2]= "testLib.dll"
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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