[plt-scheme] Question about _gcpointer and _cvector
At Wed, 11 Nov 2009 14:57:22 -0600, "Will M. Farr" wrote:
> I have a question that (I think) the manual doesn't answer regarding the
> interaction between _gcpointer and _cvector in the foreign interface. Suppose
> I have a C routine that uses the scheme_malloc_... functions to create an
> array of structs allocated under the control of the garbage collector. Then I
> do the following in the FFI:
>
> (define make-some-stuff
> (get-ffi-obj 'make_some_stuff my-library
> (_fun (n-stuff : _ufixnum) -> (stuff-array _gcpointer) ->
> (make-cvector* stuff-array _stuff-pointer n-stuff))))
>
> Does the cvector object always know that the pointer it holds should be a
> _gcpointer?
The wrapper allocated by `make-cvector*' above uses the pointer
representation (i.e., a Scheme value) that is bound to `stuff-array'.
Since that representation is based on `_gcpointer', it will retain the
underlying pointer in the correct way.
> Suppose I change the _gcpointer above to _pointer (which would be
> a mistake, but understandable)---does the cvector notice?
Yes, the resulting `_cvector' would be wrong.
> What about if the
> memory is allocated using regular malloc, and I use _gcpointer above---is the
> new cvector vulnerable to the same memory bug that led to the creation of
> _gcpointer?
Yes.
> In short, does a cvector know about the _[gc]pointer status of
> the memory block it holds?
No. `make-cvector*' just holds on to the representation of the pointer,
and the representation carries with it the GCability of the underlying
pointer.
I think it would be helpful to revise the FFI docs to make a clear
distinction between a "foreign pointer" and "a Scheme value that
represents a foreign pointer", but I haven't yet had time to try that.
Not your question, but just in case it's an issue: You should make sure
that `_stuff-pointer' is based on `_gcpointer' and not on `_pointer',
since the individual pointers in the array produced by
make_some_stuff() refer to GCable memory. Otherwise, when you extract a
value from the array with `cvector-ref', the resulting pointer
representation will not correctly retain the pointer extracted from the
array. If `_stuff-pointer' happens to be defined by `(define-cstruct
_stuff ....)', then you should use `(_gcable _stuff-pointer)' instead
of `_stuff-pointer', since the `_stuff-pointer' defined by
`define-cstruct' will be based on `_pointer'.