At Wed, 14 Mar 2018 21:56:05 +0300, Dmitry Pavlov wrote:
> 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?

Callbacks are a kind of special case, and you don't have to worry about
them moving. (I'll add that to the documentation.) You only have to
worry about keeping them from being GCed.

In the default mode, a callback can get GCed if either the Racket
procedure wrapped as a callback gets GCed or if another callback is
created for the same Racket procedure. The latter is an issue because,
by default, the procedure is used as a key to retain only the most
recent callback.

In the simpler example, the callback won't be GC'ed until `call-this`
returns, because a reference to any argument callback is retained
during the foreign call.


> 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 think you're probably on the right track here.

A box containing #f could be enough if you have only one registered
callback at a time, but that's about the same as the default mode of
relying on the callback-wrapped procedure. It won't work if you have
multiple registered callbacks, because the box value gets replaced with
every use of `_callback`.

If the issue is multiple registered callbacks, you could use a box
containing an initially empty list, and then all the callbacks created
via `_callback` will be retained --- which is good or bad, depending on
whether you want some of them to be released. A function that registers
the callback object in some way can provide better control over how
long each callback is retained.

To make the multiple-registration options more concrete, I'm enclosing
a filled-out version of your example. The "callback.rkt" file shows
four combinations of `#:keep` that should work.


If the issue isn't about multiple registrations, then my only guess is
that the box you're using doesn't remain reachable. A `let` binding of
the box won't be good enough, for example, if you don't use the box
later. I doubt that this is the problem, but if your program swaps out
namespaces at all, beware that simply defining the box as a
module-level variable won't retain the box if the module's namespace
becomes in accessible.

If I'm not guessing well enough about the problem, maybe you can refine
the question in terms of the enclosed program.

-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Attachment: callback.rkt
Description: Binary data

Attachment: callback.c
Description: Binary data

Reply via email to