On 6/26/19 6:34 AM, Christopher Howard wrote:
> Hi, I have a project going to make Racket bindings to the libhackrf C
> library installed on my Debian 9 system. I have successfully made and
> used bindings to around a dozen procedures in the library. However, when
> I get to the first really important one, my call is crashing with a
> SIGSEGV. I have this procedure defined:
>
> (define-hackrf hackrf_start_rx (_fun (_cpointer 'hackrf_device)
> (_fun _pointer -> _int)
> _pointer -> _int))
>
> This procedure takes a pointer to a device, a callback function, and
> another pointer (which I won't go into but is supposed to be null
> usually). Internally, hackrf_start_rx is a C procedure which generates a
> pthread which repeatedly calls the callback function while receiving
> data, while the original thread returns 0.
It's not safe to call Racket procedures from other OS-level threads, but
you can tell the Racket FFI to work around that restriction by using the
`#:async-apply` argument to the inner `_fun` type.
If the callback function is simple and doesn't rely on being run in any
particular thread (for example, it doesn't use any parameters like the
current output port), then you can try changing the inner function type
to the following:
(_fun #:async-apply (lambda (p) (p)) _pointer -> _int)
If that doesn't work, I think you'll have to do something more
complicated with Racket threads. Maybe someone knows a simple example?
Also, you might want to look at the `#:keep` argument. Racket's GC
doesn't know about references held by foreign libraries, so you need to
make sure that callback function doesn't get collected. (In your
example, you made `cb` a top-level definition, which means that value
won't be GC'd as long as the definition's namespace is still around.)
Ryan