MaplePointerType - Maple Programming Help

Online Help

All Products    Maple    MapleSim


Home : Support : Online Help : Programming : OpenMaple : C Application Programming Interface : Memory and Foreign Object Management : OpenMaple/C/MaplePointer

MaplePointerType

query the type of a MaplePointer in external code

MaplePointerSetType

set the type of a MaplePointer in external code

MaplePointerSetMarkFunction

associate a mark function with a MaplePointer in external code

MaplePointerSetDisposeFunction

associate a dispose function with a MaplePointer in external code

MaplePointerSetPrintFunction

associate a display function with a MaplePointer in external code

 

Calling Sequence

Parameters

Description

Examples

Calling Sequence

MaplePointerType(kv, p)

MaplePointerSetType(kv, p, type)

MaplePointerSetMarkFunction(kv, p, f)

MaplePointerSetDisposeFunction(kv, p, f)

MaplePointerSetPrintFunction(kv, p, f)

Parameters

kv

-

kernel handle of type MKernelVector

p

-

MaplePointer object

type

-

machine word sized integer type designator

f

-

hardware callback function

Description

• 

These functions can be used in external code with OpenMaple or define_external.

• 

A MaplePointer is a Maple object with embedded data and methods associated with it.  It allows arbitrary external data to be represented as a new Maple object.  Other Maple objects can contain MaplePointers.  Some operators can be overloaded using a module, so use of standard operator notation with these external objects is possible.

• 

The type given when creating a MaplePointer with ToMaplePointer can be updated with MaplePointerSetType and queried with MaplePointerType.  This identifier can be used to distinguish between MaplePointers representing different data structures. To generate a unique type identifier, use the address of an external function.

• 

If a MaplePointer's data contains references to other Maple objects, it is important to set up a mark callback using MaplePointerSetMarkFunction. Maple reuses memory containing objects that are not referred to by any active data structure.  Since Maple cannot traverse external data structures, it relies on user supplied mark functions to mark Maple objects as active. The supplied mark function is called during every sweep of the Maple garbage collector.  The callback must then call MapleGcMark(obj) for every object, obj, contained in the external data structure.

• 

A finalizer callback can be setup using MaplePointerSetDisposeFunction. The supplied callback is called when the MaplePointer object is about to be disposed of by the Maple garbage collector, on exit, or when restarting.  This callback can be used for various tasks, such as freeing externally allocated memory and closing open file handles.

• 

The MaplePointerSetPrintFunction is called whenever the MaplePointer object is about to be displayed.  The provided callback can return any valid printable Maple object that Maple  can render.  The print callback is not responsible for displaying the MaplePointer, just converting it to a non-external Maple object.

• 

It is critical that MaplePointer callbacks never raise errors, or otherwise change the execution path of code.  In addition, the mark and dispose callbacks must never create any new Maple objects.  Failure to obey these rules may result in unpredictable behavior of the active Maple session.

Examples

    #include <stdlib.h>

    #include "maplec.h"

    typedef struct _listelem {

    ALGEB val;

    struct _listelem *next;

    } ListElem;

    static MKernelVector KV;

    static void M_DECL MarkLinkedList( ALGEB p )

    {

    ListElem **list, *elem;

    list = (ListElem**)MapleToPointer(KV,p);

    elem = *list;

    while( elem ) {

        MapleGcMark(KV,elem->val);

        elem = elem->next;

    }

    }

    static void M_DECL DisposeLinkedList( ALGEB p )

    {

    ListElem **list, *elem, *cur;

    list = (ListElem**)MapleToPointer(KV,p);

    elem = *list;

    while( elem ) {

        cur = elem;

        elem = elem->next;

        free(cur);

    }

    }

    static ALGEB M_DECL ConvertLinkedList( ALGEB p )

    {

    ListElem **list, *elem, *last;

    list = (ListElem**)MapleToPointer(KV,p);

    elem = *list;

    if( !elem )

        return( ToMapleNULL(KV) );

    if( !elem->next )

        return( elem->val );

    if( !elem->next->next )

        return( ToMapleFunction(KV,ToMapleName(KV,".",TRUE),2,elem->val,

          elem->next->val) );

    if( !elem->next->next->next )

        return( ToMapleFunction(KV,ToMapleName(KV,".",TRUE),3,elem->val,

          elem->next->val,elem->next->next->val) );

    for( last=elem; last->next != NULL; last=last->next )

        ;

    return( ToMapleFunction(KV,ToMapleName(KV,".",TRUE),4,elem->val,

          elem->next->val,ToMapleName(KV,"...",TRUE),last->val) );

    }

    ALGEB M_DECL MyLinkedList( MKernelVector kv, ALGEB *args )

    {

    ListElem *elem, **list;

    ALGEB val;

    M_INT argc;

    char *code;

    argc = MapleNumArgs(kv,(ALGEB)args);

    if( argc < 1 ) {

        MapleRaiseError(kv,"at least one argument expected");

        return( NULL );

    }

    if( !IsMapleString(kv,args[1]) ) {

        MapleRaiseError(kv,"string expected");

        return( NULL );

    }

    code = MapleToString(kv,args[1]);

    if( strcmp(code,"create") == 0 ) {

        KV = kv;

        list = (ListElem**)malloc(sizeof(ListElem*));

        *list = NULL;

        val = ToMaplePointer(kv,(void*)list,(M_INT)&MarkLinkedList);

        MaplePointerSetMarkFunction(kv,val,MarkLinkedList);

        MaplePointerSetDisposeFunction(kv,val,DisposeLinkedList);

        MaplePointerSetPrintFunction(kv,val,ConvertLinkedList);

        return( val );

    }

    if( argc < 2 ) {

        MapleRaiseError(kv,

               "at least 3 arguments expected for this operation");

        return( NULL );

    }

    if( !IsMaplePointer(kv,args[2])

        || MaplePointerType(kv,args[2]) != (M_INT)&MarkLinkedList ) {

        MapleRaiseError(kv,"linked list expected");

        return( NULL );

    }

    list = (ListElem**)MapleToPointer(kv,args[2]);

    if( strcmp(code,"insert_head") == 0 ) {

        if( argc != 3 ) {

        MapleRaiseError(kv,"3 arguments expected for insert");

        return( NULL );

        }

        elem = (ListElem*)malloc(sizeof(ListElem));

        elem->next = *list;

        elem->val = args[3];

        *list = elem;

        return( ToMapleBoolean(kv,TRUE) );

    }

    else if( strcmp(code,"remove_head") == 0 ) {

        elem = *list;

        if( !elem ) {

        MapleRaiseError(kv,"linked list is empty");

        return( NULL );

        }

        *list = elem->next;

        val = elem->val;

        free(elem);

        return( val );

    }

    else if( strcmp(code,"map") == 0 ) {

        if( argc != 3 ) {

        MapleRaiseError(kv,"3 arguments expected for map");

        return( NULL );

        }

        elem = *list;

        while( elem ) {

        elem->val = EvalMapleProc(kv,args[3],1,elem->val);

        elem = elem->next;

        }

        return( args[2] );

    }

    else {

        MapleRaiseError1(kv,"unrecognized option %1",args[1]);

        return( NULL );

    }

    }

Execute the external function from Maple.

withExternalCalling&colon;

dllExternalLibraryNameHelpExamples&colon;

llistDefineExternalMyLinkedList&comma;dll&colon;

llllistcreate

ll:=

(1)

llistinsert_head&comma;ll&comma;foo&colon;

llistinsert_head&comma;ll&comma;x2&plus;2&colon;

llistinsert_head&comma;ll&comma;99&colon;

llistinsert_head&comma;ll&comma;10&comma;11&colon;

llistinsert_head&comma;ll&comma;z&colon;

ll

z&period;10&comma;11&period;...&period;foo

(2)

llistmap&comma;ll&comma;length

1 . 9 . ... . 3

(3)

llistremove_head&comma;ll

1

(4)

llistremove_head&comma;ll

9

(5)

ll

2 . 13 . 3

(6)

See Also

CustomWrapper

define_external

gc

OpenMaple

OpenMaple/C/API

OpenMaple/C/Examples

 


Download Help Document

Was this information helpful?



Please add your Comment (Optional)
E-mail Address (Optional)
What is ? This question helps us to combat spam