[Openmcl-devel] Idiom for creating arrays of C structs
John Miller
millejoh at mac.com
Thu Jun 4 06:34:19 PDT 2009
Gary,
Thank you! Everything works quite nicely now. If my brain hadn't
filled up after reading the first few paragraphs of your explanation I
am quite sure I would have learned a number of very interesting things.
Warmest regards,
John
On Jun 3, 2009, at 1:56 AM, Gary Byers wrote:
> In C, a "vector of structs" is very different from "a vector of
> pointers
> to structs"; I'm pretty sure (from the parts of the code that I can
> see)
> that what we're dealing with here is "an array of cpv structs" rather
> than "an array of pointers to cpv structs."
>
> If P is a pointer to an array of cpv structs, then in order to access
> the I'th element of P by adding (* I <size of cpv struct>) to the
> address
> of P; the resulting pointer would be a pointer to the I'th struct.
> In CCL's FFI, that'd be:
>
> (%INC-PTR ptr-returned-from-make-cpv-array (* index size-of-cpv-
> struct))
>
> And to access the value of the X component of the INDEX'th CPV struct,
>
> (pref (%INC-PTR ptr-returned-from-make-cpv-array (* index size-of-
> cpv-struct))
> #>cpVect.x) ; or whatever.
>
> There's an internal, undocumented function named CCL::%COMPOSITE-
> POINTER-REF;
> it exists solely to allow SETF to work with some macros and allows
> things
> like "setting the I'th element of an array of structures to the
> value of
> another structure", which is pretty obscure. If you see calls to
> CCL::%COMPOSITE-POINTER-REF in some macroexpansions, they'd probably
> be
> best read as if they were %INC-PTR calls.
>
> There's a little bit of syntactic sugar (another thing that may be
> referenced
> in the old release notes in the doc directory but may not have made
> it into
> the manual) that can make this a little easier:
>
> (CCL:PAREF array-pointer array-foreign-type index)
>
> Hopefully, the other arguments are self-explanatory; somewhat
> strangely, PAREF
> expects the ARRAY-FOREIGN-TYPE argument to be the type of the array
> (a pointer
> to something), rather than the type of its elements.
>
>
> Given:
>
> ? (def-foreign-type nil
> (:struct example
> (x :double-float)
> (y :double-float)))
> NIL
> ? (ccl:macroexpand-all '(pref (paref p (:* (:struct :example))
> 17) :example.x))
> (%GET-DOUBLE-FLOAT (%COMPOSITE-POINTER-REF 16 P (/ (THE FIXNUM (*
> 128 (THE FIXNUM 17))) 8)) (/ 0 8))
>
> which looks a lot scarier than it is.
>
>
> On Tue, 2 Jun 2009, John Miller wrote:
>
>> Are there any conventions/best practices to follow when working
>> with arrays of C structs that are passed back and forth from
>> foreign code? Sorry if this has already been discussed in the
>> past, but nothing jumped out at me while browsing through the
>> group's archives.
>>
>> The code in the attached file seems to work on first appearance,
>> creating an array of cpVect structures on a call to make-cpv-
>> array. I can do something like
>> (%get-ptr ptr-returned-from-make-cpv-array (* index size-of-cpv-
>> struct))
>> and get a cpVect structure back. When I pass the MACPTR returned
>> by make-cpv-array to foreign code, however, the block of memory
>> apparently turns to mush. A copy of the C code I am calling with
>> my make-cpv-array MACPTR is also in the attached file along with
>> some interactions with the Listener.
>>
>> I guess that #<A Foreign Pointer (:* (:STRUCT :CP<V>ECT))
>> #x1EF61470> is not the same as a cpVect* verts, but I am at a loss
>> to explain why and how to get the two to agree.
>>
More information about the Openmcl-devel
mailing list