# Can you call a C function that takes function pointers as arguments?

I want to use MathLink to call a function I wrote in C. However, similar to an integrator, it takes a function pointer as an argument and applies it on numbers depending on the other arguments. I know how to pass lists of reals and so on, but can you also pass pointers to functions defined in Mathematica? In the end, it should look something like this:

f[x_,y_] := x*y; Install["mycprogram"]; MyCFunction[f,1,2]


f is a function that takes two doubles and returns a double. It's fairly simple and should always be some combination of polynomials, fractions, Log and Exp.

-
You can always write a simple wrapper functions in C that don't take pointers and just calls the function that does take pointers. –  Searke Aug 6 '12 at 14:38
"Functions" in Mathematica are really rewrite rules and have no corresponding function pointer. You can get the function pointers to internal kernel functions that are written in C, but that's it. –  Oleksandr R. Aug 6 '12 at 15:53
Could you please make clear, how such functions f will look in your real world application? Is f a very complicated function which uses other non-trivial Mathematica functions (e.g. special functions ). Or will f be build from basic operations like multiplication, addition and maybe some trigonometric functions? In the first case your f should probably be calculated by the kernel, in the latter it's maybe possible to compile it down to a C function. –  halirutan Aug 6 '12 at 21:06
@halirutan: I edited the post. It should always be computable by C. –  Volker Aug 7 '12 at 7:45
Alternately, you could use Delegates and .NETLink to pass a mathematica function to a C function that uses a function pointer –  asim Aug 8 '12 at 18:28

I think there are several approaches to achieve the behavior you want but first let me point out that it is not possible to get a function pointer of a normal Mathematica function. A function pointer would require that the function was compiled but when you define a function inside Mathematica with e.g.

f[x_,y_] := x+y;


this is not the case as Oleksandr already pointed out.

Therefore, let me first give a solution which emulates the behavior you try to achieve. If you have a MathLink program or a library function which can be used inside Mathematica you can always evaluate any kind of expressions through MathLink-communication.

The idea now is to give your C-function the name of the Mathematica function (f) you want to call together with the numeric input. The you call inside your C-function the MathKernel and evaluate the call f[x,y] and use the result in the further computation.

Assume the following short library function (it is very similar to what you have to use in your MathLink program)

#include "mathlink.h"
#include "WolframLibrary.h"

DLLEXPORT mint WolframLibrary_getVersion( ) {
return WolframLibraryVersion;
}

DLLEXPORT int WolframLibrary_initialize( WolframLibraryData libData) {
return 0;
}

DLLEXPORT int func(WolframLibraryData libData, mint argc, MArgument *args, MArgument res)
{
int pkt;
mreal parm1, parm2, calc_result;
char *f;

f = MArgument_getUTF8String(args[0]);
parm1 = MArgument_getReal(args[1]);
parm2 = MArgument_getReal(args[2]);

MLPutFunction(mlp, "EvaluatePacket", 1);
MLPutFunction(mlp, f, 2);
MLPutReal(mlp, parm1);
MLPutReal(mlp, parm2);
pkt = MLNextPacket(mlp);
if (pkt == RETURNPKT) MLGetReal(mlp, &calc_result);
libData->UTF8String_disown(f);
MArgument_setReal(res, calc_result);
return LIBRARY_NO_ERROR;

}


Assuming you have stored this inside the file "myfunc.c" then you can create the ready-to-use library with

<< CCompilerDriver
CreateLibrary[{"myfunc.c"}, "myfunc", "ShellOutputFunction" :> Print]


The library is automatically put to a location where it can be found by Mathematica. When you have a closer look at the func function, you see that it expects a string and two double arguments. Then it simply uses a MathLink to evaluate the function-call f[parm1,parm2] and takes the result and just passes it back.

You can load and use this function inside your current session with

f[x_, y_] := x + y;
fun = LibraryFunctionLoad["myfunc", "func", {"UTF8String", _Real, _Real}, _Real]
fun["f", 1., 4.]

(*
Out[4]= 5.
*)

-
Good, clear answer! Just to note that if f is itself a LibraryFunction then one should be able to use LibraryFunctionPointer lfp = libData->compileLibraryFunctions->getFunctionCallPointer("f") to get its function pointer. But I haven't tried this myself, so I'm not posting an answer including this for the time being. –  Oleksandr R. Aug 8 '12 at 7:57
Thanks @OleksandrR., I had something similar in mind but didn't mention it since I was not sure whether the OP has to stick with a MathLink program. I thought about compiling the function f and then load the dll and call it manually. But even there you need the libData pointer which you usually don't have in a normal MathLink program. Or am I wrong here? –  halirutan Aug 8 '12 at 10:02
Yes, I agree. If we're restricted to MathLink, I think you've already presented the best solution. The advantage of using LibraryFunctions, of course, is the lower call overhead due to not having to serialize everything. From my own tests, MathLink has a fairly high protocol overhead too. For a simple function like f, that'll probably be significant. –  Oleksandr R. Aug 8 '12 at 11:33
@OleksandrR. Yep, thats why the answer took me so long: The OP stated that the function consists only of basic operations which would make it perfect for Compile` and a call through the Library Link. The MathLink callback is in this case only a suboptimal solution. –  halirutan Aug 8 '12 at 13:41