<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Awesome. I took at a look at ExternalArray and its subclasses. This is exactly what I was looking for! In fact I think the implementation of ExternalDoubleComplexArray does the exact type of thing I need, which is provide the ability to marshal an array of ExternalStructure to/from an underlying byte array.&nbsp;<div><br></div><div>I've never looked at Smallapack till now. Do you think that ExternalArray etc should be made part of FFI, since it has uses beyond just Smallapack? Are there caveats? I notice that many methods have a comment like "Use with caution ! Might result in segmentation fault". Is this because of verification limitations, alignment issues, or are there other concerns as well?<br><br>Nice, nice :)<br><br>Thanks,<br>Doug<br><br><br>On Jun 10, 2012, at 13:00 , Nicolas Cellier wrote:<br><br><blockquote type="cite">AFAIK, you'll have to use void * in API because arrays of structures<br></blockquote><blockquote type="cite">are not supported.<br></blockquote><blockquote type="cite">I mean FFI is not able to perform any type verification on array of<br></blockquote><blockquote type="cite">structures...<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">I created this class in Smallapack:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">ArrayedCollection subclass: #ExternalArray<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>instanceVariableNames: 'handle size data'<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>classVariableNames: 'EndianCache'<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>poolDictionaries: ''<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>category: 'Smallapack-Collection'<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- handle holds the pointer (ExternalAddress),<br></blockquote><blockquote type="cite">- size the number of elements,<br></blockquote><blockquote type="cite">- data is the object to be passed to the foreign function call (it<br></blockquote><blockquote type="cite">holds address + type information).<br></blockquote><blockquote type="cite">And here is how I had to initialize data:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">resetExternalData<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>"Reset the ExternalData object used as FFI argument.<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>This is cached in an inst-var instead of being recreated at each call.<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>However, this must be reset whenever handle is changed"<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>| cType |<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>cType := self class type.<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span>data := cType isStructureType<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>ifTrue:<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>["Arrays of structure cannot carry type checking in FFI"<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>ExternalData fromHandle: handle type: ExternalType void]<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>ifFalse:<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>["Atomic types"<br></blockquote><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>ExternalData fromHandle: handle type: self class type]<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Nicolas<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">2012/6/10 Douglas McPherson &lt;djm1329@san.rr.com&gt;:<br></blockquote><blockquote type="cite"><blockquote type="cite">All,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I'm trying to call a function in an external library which takes an array of<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">structures as one of its parameters. I can see how to define a subclass of<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">ExternalStructure, and how that creates convenient field accessors which<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">read/write an underlying ByteArray. I can see how to use such an<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">ExternalStructure to pass the struct, or a pointer to it, to a function in<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">the library. Is there a similar object I can create which allows me to<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">read/write an array of these structs (i.e. does the proper marshaling<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">to/from a ByteArray)?<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I got the i/f working by rolling my own -- directly filling up a ByteArray<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">with the right number of instances of the serialized-by-hand structure,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">creating an ExternalData instance with said ByteArray as the handle, and<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">passing this as the parameter. But this doesn't allow me to use the field<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">accessor methods created by ExternalStructure, so it feels like I'm missing<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">something.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">For concreteness, the API looks something like this:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">typedef struct<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">{<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">uint32_t someId;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">int32_t &nbsp;someInt;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">} fooStruct;<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">int32_t apiFunction<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">(<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">const &nbsp;fooStruct *foo_list,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">uint32_t foo_list_size<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">);<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Any suggestions?<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Thanks,<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Doug<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><br></blockquote><br></div></body></html>