First, let's define our C code for testing:
typedef struct my_struct {
unsigned char buffer[10];
} my_struct;
void my_struct_init(my_struct *my_s) {
for (int i = 0; i < 10; i++) {
my_s->buffer[i] = (char) i;
}
}
In Swift, we have two options:
1. Struct on the stack
var my_s: my_struct = ...
However, we have to initialize it somehow. Every struct has a default initializer
var my_s: my_struct = my_struct(buffer: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
Note that in this case the buffer[10]
has been translated to Swift as a 10-tuple
.
Now we can call:
my_struct_init(&my_s)
print("Buffer: (my_s.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
However, the more complex is the struct, the more difficult is to use the default initializer.
2. Struct on the heap
This is similar to using malloc
and free
in C:
var my_s_pointer = UnsafeMutablePointer<my_struct>.allocate(capacity: 1)
print("Buffer: (my_s.buffer)") // Buffer: (some random values)
my_struct_init(my_s_pointer)
print("Buffer: (my_s_pointer.memory.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
my_s_pointer.deallocate()
Combine both approaches
The following function will initialize any struct:
func initStruct<S>() -> S {
let struct_pointer = UnsafeMutablePointer<S>.allocate(capacity: 1)
let struct_memory = struct_pointer.pointee
struct_pointer.dealloate()
return struct_memory
}
var my_s: my_struct = initStruct()
my_struct_init(&my_s)