I want to create a struct in swift that has a small fixed number of values (say 16 floats) as instance data. It is required that this struct not store these values on the heap, so that the address of an instance of the struct is the address of the instance vars. It is also a requirement that these values be accessible internally to the struct via subscript, as Arrays are.
In C you would simply define this kind of thing thusly:
struct Matrix4x4 {
float elements[16];
...
} myMatrix;
With this code, sizeof(Matrix4x4) == 64
and also &myMatrix == &myMatrix.elements[0];
In swift, if I analogously define the elements
variable as type [Float]
, the matrix instance only contains a pointer to the array, since the Array<Float>
instance is an object stored on the heap.
Is there a way in swift to get static allocation of the instance vars without abandoning the convenience and efficiency of array-like subscripting access?
At present, this is not possible in "pure Swift". There is a long discussion on the swift-evolution mailing list starting at
which asks for such a feature, e.g. to pass a matrix structure to C functions. As far as I can see, the suggestion was well-received, but nothing concrete is planned as of now, and it is not listed in the currently active Swift proposals.
A C array
is imported to Swift as a tuple with 16 components:
and at present this seems to be the only way to define a fixed-sized structure with a given memory layout. Joe Groff from Apple writes at [swift-users] Mapping C semantics to Swift
and later in that discussion:
If the matrix type is defined in a C header file (for the sake of simplicity I am using a 2x2 matrix as example now)
then it is imported to Swift as
As mentioned above, Swift preserves the C memory layout, so that the matrix, its elements, and the first element all have the same address:
However, tuples are not subscriptable, and that makes sense if the tuple members have different types. There is another discussion on the swift-evolution mailing list
to treat "uniform tuples" as collections, which would allow subscripting. Unfortunately, this hasn't been implemented yet.
There are some methods to access tuple members by index, e.g. using
Mirror()
orwithUnsafe(Mutable)Pointer()
.Here is a possible solution for Swift 3 (Xcode 8), which seems to work well and involves only little overhead. The "trick" is to define C functions which return a pointer to the element storage:
We need two variants to make the proper value semantics work (subscript setter requires a variable, subscript getter works with constant or variable). The "swift_name" attribute makes the compiler import these functions as member functions of the
Matrix2x2
type, compareNow we can define the subscript methods in Swift:
and everything works as expected:
Of course you could also define matrix-like subscript methods
in a similar manner.