On Thu, Jun 27, 2019 at 9:52 PM Greg Troxel <g...@lexort.com> wrote: > > I have been down this path before, with guile and with lua. Basically, > if C (or non-scheme) has a pointer to a scheme object, then you need to > hold a logical reference for it and protect the scheme object, and when > the C pointer is dropped decrease the refcnt. > > I am unclear on the details of how you have a ref that gc is made aware > of. One way is to have a scheme array of the object and a count, and > have the code null out the object when the count goes to zero or > something like that. But the point is that you need to have a proxy in > the scheme world, visible to gc, when a pointer to a scheme object is > held outside of the scheme world. >
That's more or less what I had in mind, although instead of an array I would use a hash table indexed by a fundamental type (e.g. integer) which can be converted painlessly between Scheme and C. > Forcing gc is not going to be reliable. If you have a reliable scheme, > gc can happen at any random time and things will be ok. > I prepared a minimal case of the kind of C interactions that I'm trying. I'm attaching the files, the C code has to be compiled with: gcc -shared -fPIC -o mysalsa.so mysalsa.c Running the Scheme script yields something like the following: Captured: Closure without collection Argument: noitcelloc tuohtiw erusolC Captured: Closure with garbate collected Argument: So primitive values seem to be garbage collected, but closures are treated slightly differently. This is very interesting, since working with closures eliminates the need of those common "void *userdata" extra arguments. Testing continuation is going to be interesting too. Best regards. -- Isaac Jurado "The noblest pleasure is the joy of understanding" Leonardo da Vinci
typedef void (*callback_t) (void *); static callback_t saved_callback; static void *saved_arg; void give (callback_t callback, void *arg) { saved_callback = callback; saved_arg = arg; } void call () { saved_callback(saved_arg); }
(use-modules (system foreign)) (define lib (dynamic-link (string-append (getcwd) "/mysalsa"))) (define give (pointer->procedure void (dynamic-func "give" lib) '(* *))) (define call (pointer->procedure void (dynamic-func "call" lib) '())) (define (simple-closure capture) (let ([proc (lambda (arg) (display (string-append "Captured: " capture)) (newline) (display (string-append "Argument: " (pointer->string arg))) (newline))] [arg (string-reverse capture)]) (give (procedure->pointer void proc '(*)) (string->pointer arg)))) (simple-closure "Closure without collection") (call) (gc) (simple-closure "Closure with garbate collected") (gc) (call)