Call External - Maple Help

define_external

create a link to an external subroutine

 Calling Sequence define_external( functionName, arg1::type1, ..., argN::typeN, RETURN::typeR, options, LIB=libName) define_external( functionName, Language, arg1::type1, ..., argN::typeN, RETURN::typeR, options, LIB=libName) define_external( functionName, MAPLE, LIB=libName)

Parameters

 functionName - name of externally defined subroutine Language - (optional) 'C'(default),'FORTRAN', or 'JAVA' arg1..argN - names of external subroutine parameters type1..typeN - type descriptors of external subroutine parameters typeR - external subroutine return type descriptor options - calling and linkage conventions libName - name of external library containing the subroutine

Description

 • The define_external command links in an externally defined function (for example, from a DLL under Windows, or from a shared library under UNIX), and produces a Maple procedure that acts as an interface to this external function.
 • To specify the foreign function interface, at least the following information is needed.
 - Name of the external subroutine
 - Type of parameters the subroutine passes and returns
 - Name of the dll or class containing the subroutine
 • The functionName argument to define_external specifies the name of the externally-defined subroutine as it is exported from the DLL (shared library) or class file.
 • The argI::typeI arguments specify the types of the arguments to the externally defined subroutine, in the form argumentIdentifier :: typeDescriptor. For further information, see define_external/types or refer to the Advanced Connectivity chapter of the Maple Programming Guide.
 • The RETURN::typeR argument specifies the return type of the external subroutine, if any.
 • The LIB=libName argument specifies the name of the external shared library or DLL that contains the external subroutine.
 • The Maple external calling mechanism currently supports C, Fortran, and Java calling conventions.  Automatic wrapper generation is only supported for C.  There is an external API for writing custom wrappers in C and Fortran, but not Java.  The default convention used is C. To use Fortran calling, specify the name FORTRAN as a parameter to define_external.
 f := define_external('my_func', 'FORTRAN', ...);
 • To call a Java function, specify JAVA as a parameter to define_external.  Also, specify the CLASSPATH= option to point to the directories where the classes reside.  The kernelopts variables dirsep and pathsep may help to build up a platform independent path string using FileTools[JoinPath], StringTools[Join], and cat.
 f := define_external('my_func', 'JAVA', CLASSPATH="...", ...);
 • If the word WRAPPER is specified when calling a C function, Maple creates a wrapper library to do data translations. The process of creating the wrapper library requires a compiler to be set up. For available wrapper generation compiler options, see COMPILE_OPTIONS. For more information on generated wrappers, see WRAPPER.
 f := define_external(..., 'WRAPPER', ... );
 • If instead of the arg parameters, the single word MAPLE is specified, the external subroutine is assumed to accept the raw Maple data structures passed without conversion.  This assumes that the custom wrapper has been manually generated and compiled into a DLL.
 f := define_external('functionName', 'MAPLE', 'LIB'="mylib.dll");
 • By default Maple assumes that external calling functions are not thread safe.  This means that it will only allow one thread to call an external function at a time.  However by specifying THREAD_SAFE as an argument to define_external, Maple will treat the defined function as thread safe, thus allowing threads to execute the function at any time. THREAD_SAFE is not supported for Java external calling.
 f := define_external(..., 'THREAD_SAFE', ... );
 • After define_external has been used to generate a procedure, that procedure can be called just like any other Maple procedure. The appropriate Maple-to-external data type translations are done during the call, and the appropriate external-to-Maple translations are done when the call returns.
 • The procedure returned by define_external contains a call to the built-in call_external command.  The arguments to call_external are internally generated and may contain address pointers, so the procedure is saved in a special way. For more information, see define_external/save.

Examples

Consider the existence of a C function, mat_mult, defined as follows in an external library:

 void mat_mult( double *A, double *B, double *C, int I, int J, int K ) { int i, j, k; double t; for( i = 0; i < I; ++i ) for( k = 0; k < K; ++k ) { t = 0.0; for( j = 0; j < J; ++j ) t += A[i*J+j] * B[j*K+k]; C[i*K+k] = t; } }

This function takes as input two matrices, A and B, of dimensions IxJ and JxK, respectively, and space for a third matrix, C, of dimensions IxK, and computes C = AB, returning the result in the space passed for C. The matrices are assumed to be stored in row-major order, with each row immediately following the previous one in memory.

The Maple interface to this function is created by calling define_external, and passing it the description of the arguments:

 > mat_mult :=     define_external('mat_mult',     a::ARRAY(1..i,1..j,float[8]),     b::ARRAY(1..j,1..k,float[8]),     c::ARRAY(1..i,1..k,float[8]),     i::integer[4],     j::integer[4],     k::integer[4],     LIB="mat_mult.dll"):

The define_external command has generated a Maple procedure, which in this example is assigned to the Maple name mat_mult.

If the parameter WRAPPER is specified, define_external also generates, compiles, and links a C function that looks after translation of data between Maple objects and C data types.  This function has the following declaration.

 ALGEB MWRAP_mat_mult( MKernelVector kv, void ( *fn ) ( FLOAT64 *a1, FLOAT64 *a2, FLOAT64 *a3, INTEGER32 a4, INTEGER32 a5, INTEGER32 a6 ), ALGEB fn_args );

The actual mat_mult external subroutine (which was previously compiled into the "mat_mult.so" shared object library) has been linked in by define_external.

The mat_mult subroutine can now be used to perform Matrix multiplication. Because mat_mult is working with arrays of double-precision floating-point values, it makes sense to use an equivalent Maple type. Note that the default wrapper-generation language is C, while Maple uses Fortran order as the default for creating Matrices.

 > $A≔\mathrm{Matrix}\left(100,100,\left(i,j\right)↦\frac{i}{j},\mathrm{datatype}=\mathrm{float}\left[8\right],\mathrm{order}=\mathrm{C_order}\right):$
 > $B≔\mathrm{Matrix}\left(100,100,\left(i,j\right)↦j\cdot i,\mathrm{datatype}=\mathrm{float}\left[8\right],\mathrm{order}=\mathrm{C_order}\right):$
 > $C≔\mathrm{Matrix}\left(100,100,\mathrm{datatype}=\mathrm{float}\left[8\right],\mathrm{order}=\mathrm{C_order}\right):$
 > $\mathrm{mat_mult}\left(A,B,C,100,100,100\right):$