[Top][All Lists]
[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