[racket] Trouble with C->Racket callbacks passing pointers to arrays
At Mon, 20 Aug 2012 21:56:40 +0400, Dmitry Pavlov wrote:
> However, it seems that I have a similar problem with a callback
> that fills an array malloc()-ed in the C library, and I am stupid
> enough not to understand why it fails, again.
> Could you please take a look at this:
>
> int myfunc2 (int length, double *x, int (*filler) (int length, double *arr))
> {
> double *buf = (double *)malloc(length * sizeof(double));
> filler(length, buf);
> memcpy(x, buf, length * sizeof(double));
> free(buf);
> return 0;
> }
The problem in this case is that the C code receives a pointer `x' to a
GC-managed object, and the object at that memory moves during the
callback to filler(), so that memcpy(x, ....) copies to the wrong
place.
Assuming that your C code will remain oblivious to GC, you'll have to
change the call to myfunc2() to pass a reference to an object that is
either not GC-managed or won't be moved by a GC (i.e., allocated using
'atomic-interior mode):
(define (make-f64vector/immobile n)
(cast (malloc n _double 'atomic-interior)
_pointer
(_gcable (_f64vector o n))))
(define (test2)
(let ((vec (make-f64vector/immobile 3)))
....))
This example illustrates a general problem with foreign functions and
callbacks: since a GC is possible during the callback, you have to pass
the foreign function only references to things that a GC won't move.