chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] FFI: Safe referencing and allocation of Scheme objec


From: felix
Subject: Re: [Chicken-users] FFI: Safe referencing and allocation of Scheme objects from C
Date: Fri, 07 Nov 2003 14:07:50 +0100
User-agent: Opera7.11/Linux M2 build 406

On Fri, 07 Nov 2003 08:53:53 +0000, Category 5 <address@hidden> wrote:

I have a foreign callback lambda that takes a closure as an argument and
must then pass the closure to a black-box C function (as an unsigned
char *).  The C function is also passed a pointer to a callback function
defined, in this case, as a Scheme procedure with define-external.  The
C function calls the callback function with, among other things, the
pointer to the closure.  The callback function converts the pointer back
to a Scheme procedure object and then calls it:

(define foo
(foreign-callback-lambda* int
([...] (scheme-object c))
#<<EOF
return(black_box([...], scheme_callback_func, (unsigned char *)c));
EOF
))

(define-external (scheme_callback_func ((c-pointer unsigned-char) x))
void
(let ((p (pointer->object x)))
(assert (procedure? p))
(p ...)))

This actually works perfectly, except that if a GC occurs, things get
moved around such that x no longer points to the closure and the
assertion fails.

Right. One way to address is is to use C_gc_protect() inside the body of `foo':

#<<EOF
/* Warning: untested! */
C_word *data[ 1 ];
int result;
data[ 0 ] = &c;
C_gc_protect(data, 1);
result = black_box(...);
C_gc_unprotect(1);
return(result);
EOF


The thing to do seems to be to build another closure object from C
that's safe from being GC-invalidated.  A static declaration works:

static C_word p[2];
p[0] = C_make_header(C_CLOSURE_TYPE, 1);
p[1] = C_block_item(c, 0); /* c is the original closure */ return(black_box([...], scheme_callback_func, (unsigned char *)p));

Are you making sure c is only of size 1 (+ header) ?


This code, however, is not reentrant.  Replacing the static declaration
with

C_word *p = (C_word *)malloc(2*sizeof(C_word));

also works but the memory will never be reclaimed.  It seems that this
is the problem C_alloc_from_heap is meant to solve, but using that in
place of the malloc causes all Hell to break loose (the program hangs
before scheme_callback_func can do anything).

Can you send me the code that calls C_alloc_in_heap? This is normally
supposed to work...


What's the right way to do this in a GC-safe, non-memory-leaking way?


See above, C_gc_protect() should do the actually be fine. I don't understand
why your invocation of C_alloc_in_heap() fails, since this is also a valid
method.


cheers,
felix





reply via email to

[Prev in Thread] Current Thread [Next in Thread]