5
$\begingroup$

I have a c function named Func. Its argument is an array of strings. How I can implement this function by using WSTP library?

void Func(char** arrOfStrings)
{
   ...
}
$\endgroup$
3
$\begingroup$

For this application you need to go full manual; the template file mechanism will give you little-to-nothing for a list of strings.

Roughly, you need to:

  • Use Manual argument type.
  • Use raw MathLink/WSTP functions to read the data.

I suggest the following way to read and verify the data:

int n;
err = WSCheckFunction(stdlink, "List", &n);

will check that you're really receiving a List and retrieve the number of arguments. If the object on the link is not a list, the error code will be 0.

Now you write a loop to read n strings using an appropriate function: WSGetString, WSGetUTF8String or similar (depending on your encoding needs). Do note that even if you pass a non-string expression as the argument, such as an integer, this function will succeed in reading it as a string format (e.g. read 123 as "123").


However, since you got this deeply involved with WSTP, may I suggest using not installable MathLink/WSTP programs but LibraryLink to develop your library? LibraryLink provides a very efficient means to transfer basic data types such as numerical arrays. It's considerably faster than MathLink. You can still use MathLink-based passing of arguments, however, I believe you must use the ML-prefix functions instead of the WS-prefix ones (unless this restriction was released in the last version or two—I have not checked). What this means is that whatever you developed as an installable MathLink program can be transitioned to LibraryLink (except in rare situations such as MATLink where the need to interface with MATLAB would cause problems).

The few disadvantages of LibraryLink compared to installable MathLink programs are:

  • You don't get to use the template file mechanism and must manage argument passing and return on your own. If you work with lists of strings, you must do this anyway, so I don't think this is a true disadvantage in your situation.

  • If your code crashes, it will take down the kernel with it.

Finally, if you use LibraryLink, you will be able to use my LTemplate library, which mitigates some of the disadvantages. In particular, it provides a template-based class interface description, which is just as easy to use as .tm files, if not easier. This applies for standard LibraryLink argument passing, not for MathLink-based passing. However, for MathLink-based passing you also get a header file that makes argument retrieval and returning results much easier. Reading a list of strings is as easy as

mlStream ml(link);
ml >> mlCheckArgs(1); // verify number of arguments

std::vector<std::string> stringList;
ml >> stringList; // read string-list into a vector

LTemplate comes with may commented examples, including one that shows how to create a function that takes an arbitrary number of string arguments, concatenate them, and return the result. Look for it in the Examples/LinkObject subfolder. The C++ part of the code is as simple as

// Concatenate an arbitrary number of strings
void strcat(MLINK link) {
    mlStream ml(link, "strcat");

    // We do not check for the number of arguments;
    // instead, we read all arguments into a string vector
    std::vector<std::string> vec;
    ml >> vec;

    // Concatenate the strings
    std::string result;
    for (const auto &el : vec)
        result += el;

    ml.newPacket();
    ml << result;
}

The template description on the Mathematica side is simply LFun["strcat", LinkObject].

I use this library regularly for my own work, and I find it to be a huge time-saver. It makes it practical to drop down to C++ without much effort of writing boilerplate code. Now if something is relatively easy to implement in C++, I never think twice if I should do it. I can whip up a Mathematica-loadable library in a matter of minutes.

Note that unlike bare LibraryLink, LTemplate requires the use of C++ (C is not sufficient). But you can get away with very basic C++ that can be learnt by a C programmer in a couple of days.

$\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.