3
$\begingroup$

This question already has an answer here:

I have used the LibraryLink wrapper for some days. In general, there is only one result retruned by the LibraryFunction[]. Below is a simple example:

DLLEXPORT int add1(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) {
    mint I0;
    mint I1;
    I0 = MArgument_getInteger(Args[0]);
    I1 = I0 + 1;
    MArgument_setInteger(Res, I1);
    return LIBRARY_NO _ERROR;
}

However, in pratical applications, multiple results may also occur. For instance, I have a C function elevate_bspline_degree(), which has the following decalration:

void elevate_bspline_degree(double *Pw, double *U, int p)

This function mainly elevates the degree of the B-spline from p to p + 1, and calculate the new control points and new knots vector via the pointer variables Pw and U, respectively. Lastly, Corresponding value will be returned by Pw and U.

$\endgroup$

marked as duplicate by Szabolcs, Community Aug 1 '16 at 8:36

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ Basically you have two options: (1) Use MathLink-based passing and return as many results are you like (in a list). This has some performance penalties. (2) Use several LibraryLink calls to achieve what you want: one call for doing the computation, another call to retrieve the first result, another for the second result, and possibly yet another for cleaning up remaining data structures. "Managed library expressions" (look them up) make it easy to do away with the last one and have automatic cleanup. $\endgroup$ – Szabolcs Aug 1 '16 at 8:14
  • 1
    $\begingroup$ Example without the complexities of LibraryLink: Global variables: int result1, result2; Function to compute both $x^2$ and $x^4$: void compute(int k) { result1 = k*k; result2 = result1*result1; } Functions to retrieve results: int square() { return result1; } and int pow4() { return result2; }. In Mathematica you will have a wrapper function which calls these in the correct order, i.e. compute first, then retrieve result 1 then retrieve result2. In a real scenario you probably need to allocate memory for result1 and result2 (malloc or similar). So you may need ... $\endgroup$ – Szabolcs Aug 1 '16 at 10:54
  • 1
    $\begingroup$ ... yet another function which frees the memory. This will be called after the results have been retrieved. Handling this may be easier if you use managed library expressions. Take a look e.g. at how TetGenLink and TriangleLink (builtin packages) work. First you create a "triangle expression" with TriangleCreate. Then you add data to it (e.g. set point coordinates). Then you call a function to compute something. Then you can retrieve multiple results, each with its own function. In Mathematica 9, finally you had to TriangleDelete the expression. In M10 you can just Clear it. $\endgroup$ – Szabolcs Aug 1 '16 at 10:55
  • 1
    $\begingroup$ @Vahagn Yes, there are potential problems with this. It is important to call the functions in a very specific order, otherwise "bad things" may happen. With certain designs you may crash the kernel (e.g. trying to retrieve a result for which memory is not allocated). Thus a package should not expose all these functions to the end user, only higher level functions which call these low level functions internally in the correct order. Other than this, I see no problems, and I also don't see any better ways which are also performant to return multiple results. $\endgroup$ – Szabolcs Aug 1 '16 at 14:50
  • 1
    $\begingroup$ @Vahagn MathLink would be a better way (from a design viewpoint), but it's clearly slower for transferring large arrays. But then if you use managed library expressions, then some of the problems go away, you get automatic cleanup, and easy way to maintain multiple instances of your data structure on the C side, etc. The only problem is that it is really a lot of work to work with managed library expression. That's why I wrote LTemplate—it makes all this possible with much less code. $\endgroup$ – Szabolcs Aug 1 '16 at 14:52
3
$\begingroup$

No, it is not possible. As with any programming language a function returns only one result. It may be an array a pointer or a whole object as it is in C/C++, but it is still one return variable. You may have noticed working with Mathematica that Module and Block also return one variable, you can just wrap them in {}, and get list of return values though. Any way if you go to the directory of your Mathematica -> System Files -> Includes -> C -> WolframLibrary.h you will see that MArgument is defined as

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

Soo, no. You can't. However in your case you can always use

MTensor T0;
int err;
double *data;
const int dims[2] = {1,2};
err = libData->MTensor_new( MTensor_Type_Real, 1, dims, &T0);
data = libData->MTensor_getRealData(T0);
data[0] = Pw;
data[1] = U; 
MArgument_setMTensor(Res,T0);
return LIBRARY_NO_ERROR;

Or Alternatively:

You can always write several LibraryLink functions that return each of your desired outputs. Then write a wrapper in Mathematica that calls all of these functions gets their results and prints one by one.

$\endgroup$
  • $\begingroup$ In my case, the variable Pw is a matrix, rather than a number, and the U is a vector, instead of a number. So I cannot directly use the following assgnment statement: data[0] = Pw; data[1] = U; For your Alternatively, I thought about that, however, the elevate_bspline_degree() is a whole, that means I need to call that function two times. $\endgroup$ – xyz Aug 1 '16 at 3:43
  • $\begingroup$ I see, try using an RawArray of MTensors then. I think it is possible to work around that issue. However RawArrays are supported starting from 10.4. Another suggestion is if the dimensions of $Pw$ and $U$ are close, e.g. NxM and 1xN or 1xM you can pad one tensor with another and return that. An ugly method is to print somewhere in a file and then import the result. An uglier still method is to turn everything into a string stream and return char* for later formatting. $\endgroup$ – Vahagn Tumanyan Aug 1 '16 at 11:21

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