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: Category 5
Subject: Re: [Chicken-users] FFI: Safe referencing and allocation of Scheme objects from C
Date: Fri, 07 Nov 2003 14:22:41 +0000
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (berkeley-unix)

felix <address@hidden> writes:

> 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

I have just tried this and the result is strange.  The callback function
is called twice from black_box successfully, but the third time it's
called the assertion fails (the pointer is no longer pointing to the
procedure object).  The code matches your example exactly.

(black_box is an I/O function that sits around and receives things and
repeatedly calls scheme_callback_func with them.)

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

Well, the Data Representation section of the manual says:

    procedures: special vector object (type bits C_CLOSURE_TYPE). The
    first slot contains a pointer to a compiled C function.

Does this not mean that a procedure object will always be 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...

(define foo
  (foreign-callback-lambda* int
   (((c-pointer (struct "bar")) p) (int cnt) (scheme-object c))
   #<<EOF
   C_word *new_c;

   new_c = C_alloc_in_heap(2);
   new_c[0] = C_make_header(C_NEW_C_TYPE, 1);
   new_c[1] = C_block_item(c, 0);

   return(black_box(p, cnt, scheme_callback_func, (unsigned char *)new_c));
EOF
))

As an aside, can you explain a little about the relationship between the
C_alloc, C_alloc_in_heap, C_gc_protect and C_gc_unprotect routines?

>From what I can make out, C_alloc and C_alloc_in_heap allocate memory
from the C stack/nursery and the GC'd heap, respectively.  It seems that
it's only safe to C_alloc things that will be passed on immediately to a
Scheme procedure defined with define-external, because the callback
process magically registers the allocated objects properly with the GC.
On the other hand, C_alloc_in_heap is safer in some sense because the
memory is still valid after the foreign procedure returns - but how does
the GC know when to reclaim it?

I couldn't guess from the documentation that C_gc_protect could be used
as in your example above.  Such examples are extremely helpful.  (Even
though this one doesn't seem to be working quite right yet...)

Thanks for all your help!  Chicken is fantastic and working with it is
quite an adventure.

-- 





reply via email to

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