[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