Using 3rd party external functions in Compiled procedures

July 27 2010 acer 10211
Maple

5

There are two pieces of extended functionality that I quite often want from the Maple Compiler. The first (task A) is to be able to link in and use an arbitrary function from some other external ("3rd party") shared library, within my Compile'd Maple procedure. The second (task B) is to directly call the compiled Maple procedure from within some computational routine in a 3rd party shared library (which I would then access using define_external). This post is about the first of those, task A.

Background detail (Example follows):

First, let's dig into the Maple Library code for the Compiler, to make get some illumination. (Run these commands only if you want to see some of how it works underneath. The working example is at the end.)

  eval(Compiler:-Compile); # ok, it's just a straight pass-off

eval(Compiler:-Compile1); # ahh,it's not an export of the package

kernelopts(opaquemodules=false): # so we can poke around the package
eval(Compiler:-Compile1); # fascinating stuff

op(1,eval(Compiler:-Compile1)); # just its parameter list

So, there are more optional parameters to Compile than just the ones documented on ?Compiler:-Compile ('trace', 'optimize', and 'warnings'). Consider the option named 'nativeprocs', which must be of type list. Look at these lines of code,

  showstat(Compiler:-Compile1,29..32);

So, what does Compiler:-NativeProcs:-Add do, and what types of arguments does it expect to see in the passed list?

  showstat(Compiler:-NativeProcs:-Add);

It appears to be constructing a table, npTab, containing things which are referred to as mname::string (Maple name), sig::type (signature), cname::string (C name), and library::string.

The hardest one to guess or figure out is the signature, sig::type. Let's look at some more Library internals.

  exports(Compiler:-NativeProcs);

showstat(Compiler:-NativeProcs:-GetDeclaration);

That body of that last routine has some hints about the acceptable form of that signature argument. One may enjoy staring at it.

Example:

The following example is being run on Linux. It uses the native Bessel J0, which is C function j0 inside the native Linux system's libm.so math library.

> p := proc(x::float) Jzero(x); end proc:
>
> cp := Compiler:-Compile(p,
> 'nativeprocs'=[["Jzero",
> 'procedure'['float']('float'),
> 'cname'="j0",
> 'library'=" -L/usr/lib -lm "]]):
Warning, the function names {Jzero} are not recognized in the target language
>
> BesselJ(0,3.2);
-0.3201881697

> cp(3.2);
-0.320188169657123045

That was in Maple 14, on 32bit Linux. Of course, the 'library' part would likely have to be different on another operating system. Maybe someone would care to post a MS-Windows equivalent (using the .dll from GSL?)

Endnote:

There it is. The "unknown" function calls (like to `Jzero`) can be mapped out by the Compiler to something wholly separate from Maple. And the Maple procedure that gets compiled could, of course, be much longer and more involved. This isn't just a fast way to get access to (only) a fast Bessel J0 (since one could use define_external directly for just that).

It also works even if I have `Jzero` assigned in the Maple session as a procedure which calls BesselJ, thus allowing `p` also to work fine as an uncompiled proc.

Further staring at the body of Compiler:-NativeProcs:-GetDeclaration may give more insights into the general forms accepted for the function signature. Suggestions are welcome.

If you want to see code for Task B, as mentioned at top, then feel free to add your vote.

acer

Please Wait...