define_external(MAPLE)
connect to a custom external wrapper library
Calling Sequence
Parameters
Description
Examples
define_external( functionName, MAPLE, LIB=libName)
functionName
-
name of externally defined function
MAPLE
keyword indicating the wrapper library is custom built
libName
name of external library containing the function
For complete control over data conversions, Maple allows modification of existing wrappers and creation of custom wrappers. There is an extensive API of functions available to external programs called from Maple using define_external.
If instead of the arg parameters, the single word MAPLE is specified, the external function 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.
When declaring a wrapper external function in Maple via define_external, there is no need to specify the parameter types. The wrapper always gets the same two arguments -- a kernel handle and an expression sequence (dag) of arguments.
C wrappers need to include the file maplec.h. This file is located in the extern/include subdirectory of your Maple installation.
The main entry point in your custom wrapper should accept two parameters, the MKernelVector handle and something of type ALGEB. The entry point prototype will look like the following.
ALGEB MWRAP_mult(
MKernelVector kv,
ALGEB fn_args
);
Note that the generated wrapper uses a slightly different argument list than the custom wrapper. The custom wrapper does not get a pointer to the main external function. The generated wrapper main entry point for a function that takes two int arguments and returns an int has the following prototype.
INTEGER32 (*fn) ( INTEGER32 a1, INTEGER32 a2 ),
When Maple calls this main entry point, it passes the kernel handle and an EXPSEQ dag. Index directly into the EXPSEQ dag to get at the raw Maple arguments. Use the NumArgs function available in maplec.dll to determine the number of arguments.
For more information on the external API, refer to the Maple Programming Guide section External Function Interface in the Advanced Connectivity chapter. Alternately, refer directly to the C header file, extern/include/maplec.h
Consider the following C wrapper function saved in mylib.dll. It takes three arguments, args[1] is a Matrix, args[2] is an integer, and args[3] is a string. The function finds all the values in args[1] that satisfy the relation "<", ">", "=", or "!=" args[2]. The relation is given in args[3]. The number of entries found is displayed, and a vector result is returned.
;include "maplec.h"
ALGEB ExtractElems( MKernelVector kv, ALGEB args )
{
char relation;
int n, elems, result_elems, count, i;
ALGEB Matrix, result;
RTableSettings settings;
M_INT bounds[2];
/*
basic argument checking
*/
if( MapleNumArgs(kv,args) != 3
|| !IsMapleRTable(kv,(ALGEB)args[1])
|| !IsMapleInteger32(kv,(ALGEB)args[2])
|| !IsMapleString(kv,(ALGEB)args[3]) )
MapleRaiseError(kv,"usage: ExtractElems(Matrix,integer,string)");
}
find more about the Matrix
Matrix = (ALGEB)args[1];
RTableGetSettings(kv,&settings,Matrix);
if( settings.data_type != RTABLE_INTEGER32
|| settings.storage != RTABLE_RECT
|| !IsMapleNULL(kv,settings.index_functions) )
/* not the format we wanted -- make a copy */
settings.data_type = RTABLE_INTEGER32;
settings.storage = RTABLE_RECT;
settings.index_functions = ToMapleNULL(kv);
settings.foreign = FALSE;
Matrix = RTableCopy(kv,&settings,Matrix);
get a pointer to the actual Matrix data
elems = (int)RTableDataBlock(kv,Matrix);
translate the other arguments
n = MapleToInteger32(kv,(ALGEB)args[2]);
relation = MapleToString(kv,(ALGEB)args[3]);
scan over the elements linearly -- we don't need to look at
RTableNumDimensions, RTableLowerBound, and RTableUpperBound
because we don't care where the elements are, just what they are.
first count the elements that satisfy the relation
count = 0;
switch( relation[0] ) {
case '>':
for( i=0; i<RTableNumElements(kv,Matrix); ++i )
if( elems[i] > n ) count++;
break;
case '<':
if( elems[i] < n ) count++;
case '=':
if( elems[i] == n ) count++;
case '!':
if( elems[i] != n ) count++;
default:
MapleRaiseError1(kv,"invalid relation %1",(ALGEB)args[3]);
create a new Array to store the result
RTableGetDefaults(kv,&settings);
settings.subtype = RTABLE_ARRAY;
settings.num_dimensions = 1;
bounds[0] = 1;
bounds[1] = count;
result = RTableCreate(kv,&settings,NULL,bounds);
fill in the result
result_elems = (int)RTableDataBlock(kv,result);
if( elems[i] > n ) result_elems[count++] = elems[i];
if( elems[i] < n ) result_elems[count++] = elems[i];
if( elems[i] == n ) result_elems[count++] = elems[i];
if( elems[i] != n ) result_elems[count++] = elems[i];
display a message
InitMaplePrintf(kv);
MaplePrintf("%d element%s satisfied the relation elem[i] %s %d.\n\n",
count, count==1 ? "" : "s",relation,n);
return the Array we created
return( result );
After compiling this function into a .dll, it can be used directly in Maple as follows.
extract≔define_external⁡ExtractElems,MAPLE,LIB=mylib.dll:
M≔Matrix⁡4,4,i,j↦4⋅i+j−12:
extract⁡M,0,<
−7,−3,−6,−2,−5,−1,−4
7 elements satisfied the relation elemi<0.
extract⁡M,0,>
1,5,2,6,3,7,4,8
8 elements satisfied the relation 0<elemi.
extract⁡M,0,=
0
1 element satisfied the relation elemi=0.
extract⁡M,0,!=
−7,−3,1,5,−6,−2,2,6,−5,−1,3,7,−4,4,8
15 elements satisfied the relation elemi≠0.
See Also
COMPILE_OPTIONS
define_external
define_external/types
ProgrammingGuide/AdvancedConnectivity
SharedLibrary
WRAPPER
Download Help Document