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
MaplePointerType(kv, p)
MaplePointerSetType(kv, p, type)
MaplePointerSetMarkFunction(kv, p, f)
MaplePointerSetDisposeFunction(kv, p, f)
MaplePointerSetPrintFunction(kv, p, f)
kv
-
kernel handle of type MKernelVector
p
MaplePointer object
type
machine word sized integer type designator
f
hardware callback function
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.
#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;
cur = elem;
free(cur);
static ALGEB M_DECL ConvertLinkedList( ALGEB p )
ListElem **list, *elem, *last;
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;
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");
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");
if( !IsMaplePointer(kv,args[2])
|| MaplePointerType(kv,args[2]) != (M_INT)&MarkLinkedList ) {
MapleRaiseError(kv,"linked list expected");
list = (ListElem**)MapleToPointer(kv,args[2]);
if( strcmp(code,"insert_head") == 0 ) {
if( argc != 3 ) {
MapleRaiseError(kv,"3 arguments expected for insert");
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 ) {
if( !elem ) {
MapleRaiseError(kv,"linked list is empty");
*list = elem->next;
val = elem->val;
free(elem);
else if( strcmp(code,"map") == 0 ) {
MapleRaiseError(kv,"3 arguments expected for map");
elem->val = EvalMapleProc(kv,args[3],1,elem->val);
return( args[2] );
else {
MapleRaiseError1(kv,"unrecognized option %1",args[1]);
Execute the external function from Maple.
with⁡ExternalCalling:
dll≔ExternalLibraryName⁡HelpExamples:
llist≔DefineExternal⁡MyLinkedList,dll:
ll≔llist⁡create
llist⁡insert_head,ll,foo:
llist⁡insert_head,ll,x2+2:
llist⁡insert_head,ll,99:
llist⁡insert_head,ll,10,11:
llist⁡insert_head,ll,z:
ll
z·10,11·...·foo
llist⁡map,ll,length
1 . 9 . ... . 3
llist⁡remove_head,ll
1
9
2 . 13 . 3
See Also
CustomWrapper
define_external
gc
OpenMaple
OpenMaple/C/API
OpenMaple/C/Examples
Download Help Document