I have a question about what the best way to achieve something with Chicken's FFI might be. This is based on problems I'm having with the svn-client egg (so the actual code is more complex, this is just a simplification) for some modifications that I'm making to implement some new functionality in Svnwiki.
Lets say I have the following C structure: struct closure { void *data; void *proc(void *data); }; Lets say I have a function that builds one such structure and returns it: void create_closure(void *data, void *proc (void *)); (Please ignore syntax errors in the above C code; the intention should be clear.) Now, if I want to make create_closure callable from Scheme, I'm doing the following: (define-record c-closure ptr) (define (make-c-closure-with-finalizer x) (set-finalizer! x (foreign-lambda void "free_closure" (pointer "closure"))) (make-c-closure x)) (define-foreign-type c-closure-type (pointer "closure") c-closure-ptr make-c-closure-with-finalizer) (define-external (call_the_proc (scheme-object proc)) scheme-object (proc)) (define create-closure (foreign-lambda* c-closure ((scheme-object proc)) "return(create_closure(proc, call_the_proc));")) This, evidently, has problems. If the programmer does (create-closure (lambda () (foobar))) , the dependency of the resulting c-closure on the parameter passed to create-closure is not registered anywhere. So it may get GCed. And, furthermore, IIRC, it may get moved to a different address so the C pointer data will be rendered invalid. So what's the best way to solve this? One idea I had was to do the following (plus tweaks to call_the_proc to de-ref the GC root): (define create-closure (let ((obj ((foreign-lambda* c-closure ((scheme-object proc)) #<<EOF void *root = CHICKEN_new_gc_root(); CHICKEN_gc_root_set(root, proc); return(create_closure(root, call_the_proc)); EOF ) proc))) (set-finalizer! (c-closure-ptr obj) (foreign-lambda* void ((c-closure obj)) "CHICKEN_delete_gc_root(obj->data);")) obj)) I actually don't think this would work: there could be loops if the Scheme-level closure depends on an object that is eventually modified to depend on the C-level closure object (the object returned by create-closure) so even if there are no other references to these objects, they won't be GCed. So how should I solve this problem? Thanks. Alejo. http://azul.freaks-unidos.net/ _______________________________________________ Chicken-users mailing list Chicken-users@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-users