Arrays of Structures
Homogeneous. arrays of ExternalStructures can be represented in Dolphin by instances of the generic StructureArray class. StructureArray implements the Smalltalk collection protocols such that when one accesses the elements one gets an instance of the appropriate ExternalStructure class that references the appropriate area of storage in the StructureArray, and which can therefore be used to read or update the values there. For example the Canvas method to draw polygons needs to pass an array of POINTs to a GDI function, and so it uses a StructureArray to convert from a Smalltalk collection to a properly formatted memory block containing the same values:
"Draw a filled polygon from the collection of points."
| points count |
count := collectionOfPoints size.
points := StructureArray length: count elementClass: POINTL.
points with: collectionOfPoints do: [:pointl :point | pointl x: point x; y: point y].
polygon: self asParameter
Toolbar uses a StructureArray of TBBUTTON to add buttons to a Windows toolbar control in a similar fashion in its #basicAddItems: method.
StructureArrays are commonly used to access embedded arrays of structures in other structures. For example from LOGPALETTE (which describes a Windows palette):
"Answer the receiver's palPalEntry field as a Smalltalk object."
^StructureArray fromAddress: (bytes yourAddress + 4) length: 256 elementClass: PALETTEENTRY
There are many other examples of the use of StructureArray in the image, often associated with the StructureArrayField field type.
StructureArray is actually generic enough to fulfil the roles of the scalar value array classes. For example we could represent a DWORDArray by constructing a StructureArray with DWORDs as the element class. Although not quite the same thing (the elements are enumerated or accessed as DWORDs rather than as Smalltalk Integers) it would do the job. Apart from the fact that this would be less convenient, performance would also suffer. Accessing the elements of StructureArrays, or enumerating them, is quite slow because an ExternalStructure instance has to be constructed to represent each element, which is expensive. Also the calculation to work out the offsets of each element is more complex than required for a single case, and must take account of packing and alignment issues that would generally be hard-wired into the offset calculation for a specific case. Consequently, if performance is an issue, one should consider adding a specialized ExternalArray type to represent arrays of a particular structure type.