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.
callback.rkt
Description: Binary data
callback.c
Description: Binary data