custom wrappers - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

Online Help

All Products    Maple    MapleSim


define_external(MAPLE)

connect to a custom external wrapper library

 

Calling Sequence

Parameters

Description

Examples

Calling Sequence

define_external( functionName, MAPLE, LIB=libName)

Parameters

functionName

-

name of externally defined function

MAPLE

-

keyword indicating the wrapper library is custom built

libName

-

name of external library containing the function

Description

• 

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.

    ALGEB MWRAP_mult(

      MKernelVector kv,

      INTEGER32 (*fn) ( INTEGER32 a1, INTEGER32 a2 ),

      ALGEB fn_args

    );

• 

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

Examples

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 '<':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] < n ) count++;

         break;

     case '=':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] == n ) count++;

         break;

     case '!':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] != n ) count++;

         break;

     default:

         MapleRaiseError1(kv,"invalid relation %1",(ALGEB)args[3]);

     }

     /*

       create a new Array to store the result

     */

     RTableGetDefaults(kv,&settings);

     settings.data_type = RTABLE_INTEGER32;

     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);

     count = 0;

     switch( relation[0] ) {

     case '>':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] > n ) result_elems[count++] = elems[i];

         break;

     case '<':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] < n ) result_elems[count++] = elems[i];

         break;

     case '=':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] == n ) result_elems[count++] = elems[i];

         break;

     case '!':

         for( i=0; i<RTableNumElements(kv,Matrix); ++i )

             if( elems[i] != n ) result_elems[count++] = elems[i];

         break;

     }

     /*

       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.

extractdefine_externalExtractElems&comma;MAPLE&comma;LIB=mylib.dll&colon;

MMatrix4&comma;4&comma;i&comma;j4i+j12&colon;

extractM&comma;0&comma;<

−7&comma;−3&comma;−6&comma;−2&comma;−5&comma;−1&comma;−4

(1)

7 elements satisfied the relation elemi<0.

extractM&comma;0&comma;>

1&comma;5&comma;2&comma;6&comma;3&comma;7&comma;4&comma;8

(2)

8 elements satisfied the relation 0<elemi.

extractM&comma;0&comma;=

0

(3)

1 element satisfied the relation elemi=0.

extractM&comma;0&comma;!=

−7&comma;−3&comma;1&comma;5&comma;−6&comma;−2&comma;2&comma;6&comma;−5&comma;−1&comma;3&comma;7&comma;−4&comma;4&comma;8

(4)

15 elements satisfied the relation elemi0.

See Also

COMPILE_OPTIONS

define_external

define_external/types

ProgrammingGuide/AdvancedConnectivity

SharedLibrary

WRAPPER