I'm aware of this answer, but this is not the same thing - thats passing a pointer to be initialised with an allocation.
I'm interfacing with a C library that has the following structure definition:
typedef struct myStruct { unsigned char var [50]; } myStruct;
There is a function to which you pass the address of the structure - normally stack based not heap, thus:
myStruct mine;
initMyStruct(&mine);
This initialises the content of the struct - the caller does not know the internal format of the memory, hence the obfuscation.
In Swift, I'm creating a class which will encapsulate the structure and interface with other C functions which operates on it.
class MyClass {
var mine : myStruct
init() {
initMyStruct(&mine)
// Error: Variable 'self.msg' passed by reference before being initialized
}
}
I can't for the life of me work out how to initialise the structure, or use a point instead if that is an alternative.
mine = myStruct()
// Fails because you aren't providing the value of the member 'var'
mine = myStruct((CUnsignedChar(), CUnsignedChar(), /*... repeat to 50 */))
// Cannot find an overload for 'init' that accepts the arguments
Please note, this is passing the address of an already allocated (stack based) structure to a function that has been imported as
CInt initMyStruct(str: CMutablePointer<myStruct>)
It is NOT passing a pointer to be allocated by the C library in question which seems to be a more common requirement and is answered elsewhere.
Swift currently doesn't support fixed size arrays either.
I can't see how to satisfy the initialisation of the structure or make Swift think that it is going to be done so by the call.
Any help greatly appreciated!
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)
Believe it or not, you can initialize C Struct just like Swift Struct. Xcode even autocompletes member names for you!
In this Particular case,
var when = timespec(tv_sec:0, tv_nsec:0)
Will set when
to epoch.
And here is a magical initializer that gives you any blank struct:
func blankof<T>(type:T.Type) -> T {
var ptr = UnsafePointer<T>.alloc(sizeof(T))
var val = ptr.memory
ptr.destroy()
return val
}
The above example would be:
var when = blankof(timespec)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With