ctx->opFrame = opf;
if(IS_CCODE(code)) {
- naRef result = (*PTR(code).ccode->fptr)(ctx, obj, nargs, args);
+ struct naCCode *ccode = PTR(code).ccode;
+ naRef result = ccode->fptru
+ ? (*ccode->fptru)(ctx, obj, nargs, args, ccode->user_data)
+ : (*ccode->fptr)(ctx, obj, nargs, args);
if(named) ERR(ctx, "native functions have no named arguments");
ctx->opTop = ctx->opFrame;
PUSH(result);
struct naCCode {
GC_HEADER;
- naCFunction fptr;
+ union {
+ naCFunction fptr; //<! pointer to simple callback function. Invalid if
+ // fptru is not NULL.
+ struct {
+ void* user_data;
+ void(*destroy)(void*);
+ naCFunctionU fptru;
+ };
+ };
};
struct naGhost {
naFree(o->constants); o->constants = 0;
}
+static void naCCode_gcclean(struct naCCode* c)
+{
+ if(c->fptru && c->user_data && c->destroy) c->destroy(c->user_data);
+ c->user_data = 0;
+}
+
static void naGhost_gcclean(struct naGhost* g)
{
if(g->ptr && g->gtype->destroy) g->gtype->destroy(g->ptr);
case T_VEC: naVec_gcclean ((struct naVec*) o); break;
case T_HASH: naiGCHashClean ((struct naHash*) o); break;
case T_CODE: naCode_gcclean ((struct naCode*) o); break;
+ case T_CCODE: naCCode_gcclean((struct naCCode*)o); break;
case T_GHOST: naGhost_gcclean((struct naGhost*)o); break;
}
p->free[p->nfree++] = o; // ...and add it to the free list
{
naRef r = naNew(c, T_CCODE);
PTR(r).ccode->fptr = fptr;
+ PTR(r).ccode->fptru = 0;
+ return r;
+}
+
+naRef naNewCCodeU(struct Context* c, naCFunctionU fptr, void* user_data)
+{
+ return naNewCCodeUD(c, fptr, user_data, 0);
+}
+
+naRef naNewCCodeUD( struct Context* c,
+ naCFunctionU fptr,
+ void* user_data,
+ void (*destroy)(void*) )
+{
+ naRef r = naNew(c, T_CCODE);
+ PTR(r).ccode->fptru = fptr;
+ PTR(r).ccode->user_data = user_data;
+ PTR(r).ccode->destroy = destroy;
return r;
}
#endif
typedef struct Context* naContext;
-
+
// The function signature for an extension function:
typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
+// The function signature for an extension function with userdata passed back:
+typedef naRef (*naCFunctionU)
+ (naContext ctx, naRef me, int argc, naRef* args, void* user_data);
+
// All Nasal code runs under the watch of a naContext:
naContext naNewContext();
void naFreeContext(naContext c);
naRef naNewVector(naContext c);
naRef naNewHash(naContext c);
naRef naNewFunc(naContext c, naRef code);
+
+/**
+ * Register extension function
+ *
+ * @param fptr Pointer to C-function
+ * @param user_data Optional user data passed back on calling the function
+ * @param destroy Optional callback called if function gets freed by garbage
+ * collector to free user data if required.
+ */
naRef naNewCCode(naContext c, naCFunction fptr);
+naRef naNewCCodeU(naContext c, naCFunctionU fptr, void* user_data);
+naRef naNewCCodeUD(naContext c, naCFunctionU fptr, void* user_data,
+ void (*destroy)(void*));
// Some useful conversion/comparison routines
int naEqual(naRef a, naRef b) GCC_PURE;