10
$\begingroup$

I need to return a string from a LibraryLink function. The documentation states:

When a string is returned as a result, the Wolfram Language accesses the memory to convert it to its own internal string format, but does not attempt to free the memory. Thus, if your program allocates a string for a result, it also needs to free that memory, but in a separate function from the one setting the string result, since the Wolfram Language needs to access the string memory after the library function has returned.

Does this really mean that I need to have two functions to be able to return the string, one to return it and one to free the memory? Is there really no simpler way?

Based on my interpretation the minimal work needed to return a dynamically allocated string is what's shown at the end of the post. Is this correct? This looks quite tedious.

Is there a way to let Mathematica manage the memory for the string (including allocation and freeing, as with MTensors)?

(To be fair: it can be expected that in many cases one would want to return a pre-defined string in which case there is no need to free it. Sometimes the string is dynamically allocated though, and it becomes necessary to free it.)


In this example use C++'s std::string to save some work, but using simple char * in C would be analogous, with some added tedium.

std::string *str = NULL; // ugly global variable

extern "C" DLLEXPORT int get_string(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    str = new std::string("some string to return");
    MArgument_setUTF8String(Res, const_cast<char *>(str->c_str()));
    return LIBRARY_NO_ERROR
}

extern "C" DLLEXPORT int free_string(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    delete str;
    str = NULL;
    return LIBRARY_NO_ERROR
}

Then in Mathematica:

iGetString = LibraryFunctionLoad["lib", "get_string", {}, "UTF8String"]
iFreeString = LibraryFunctionLoad["lib", "free_string", {}, "Void"]

getString[] := 
  PreemptProtect@AbortProtect@Module[{str},
    str = iGetString[];
    iFreeString[];
    str
  ]
$\endgroup$
1
  • 1
    $\begingroup$ Here is a complete example of the technique showed by Szabolcs (the OP) using C instead of C++. $\endgroup$ Commented Apr 2, 2015 at 16:15

1 Answer 1

5
$\begingroup$

You are correct, but it's not necessary to expose the free_string method. Just delete the string you allocated in subsequent calls to get_string. Something like this …

if (str!=NULL) {
  delete str;
}    
str = new std::string("some string to return");
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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