Hello,

I am doing a Racket interface for a C library and the
garbage collector is my trouble again. I am asking for
advice from Racket FFI masters (actually, from anybody
who knows how to keep persistent callbacks from a C
side to Racket).


Earlier I was doing this:

(define _callback (_fun _int -> _void))

(define (my-variable-external-to-callback (make-hash))

(define call-this
  (get-ffi-obj
    "callThis" mylib
    (_fun (callback : _callback)
          -> _void)))

(define (my-callback number) ... my-variable-external-to-callback ...)

(call-this my-callback)



And all was fine, even when the callback was called multiple times.
Recently I got inventive and started doing this:



(define _callback (_fun _int -> _void))

(define (my-variable-external-to-callback (make-hash))

(define create-caller
  (get-ffi-obj
    "createCaller" mylib
    (_fun -> _pointer)))

(define set-callback
  (get-ffi-obj
    "setCallback" mylib
    (_fun _pointer _callback -> _void)))

(define call-that
  (get-ffi-obj
    "callThat" mylib
    (_fun _pointer -> _void)))

(define (my-callback number) ... my-variable-external-to-callback ...)

(let ((caller (create-caller)))
  (set-callback caller my-callback)
  (call-that caller))


And it crashes, though not on the first call to the callback.
(collect-garbage) makes it crash faster.
Without accessing variables that are outside the callback's
scope, it works, though that may be just luck.
I suspect that "my-callback" or something linked to it are moved
in memory by the garbage collector, and the pointer kept by
the C library is no longer valid. In the first simpler
case, that does not happen because it sets and uses the
callback in the single FFI call, right?


The Racket FFI manual summarizes my problem in a most
neat and elegant wording:

If the foreign function invokes Racket callbacks, however, beware that values 
managed by the Racket garbage collector might be moved in memory by the garbage 
collector.

What can be done about it, though?
The further reading of the manual gave me the idea that I could provide
a #:keep argument to _fun as a remedy, but, well, either it is not
for what I am thinking it is for, or I am using it incorrectly.
I bind a (box #f), pass it to _fun, but my program still crashes.


I will be very grateful for a single example of how to pass a Racket
function to C and call it back *later*.


Best regards,

Dmitry



P.S. The example, of course, is made up and reflects my current
hypothesis about the crash, which may be wrong. Also, I have all
this not on top level, but inside a function, but I guess that
does not matter.

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to