chicken-users
[Top][All Lists]
Advanced

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

[Chicken-users] FFI: Safe referencing and allocation of Scheme objects f


From: Category 5
Subject: [Chicken-users] FFI: Safe referencing and allocation of Scheme objects from C
Date: Fri, 07 Nov 2003 08:53:53 +0000
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (berkeley-unix)

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.

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));

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).

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

-- 





reply via email to

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