fang
1
I am working on a mixed project with swift and C.
I use modulemap,so I can use C in swift.
The C code is like
int write_message_data(model_struct *model, unsigned char *message_data,
int message_data_size)
which convert to swift is
public func write_message_data(_ model: UnsafeMutablePointer<model_struct>!, _ message_data: UnsafeMutablePointer<UInt8>!, _ message_data_size: Int32) -> Int32
Then I need to use a Data produced by the protobuf,set it as message_data.
But I can not convert this Data to UnsafeMutablePointer!
I just want Data's pointer and fits the type.
eskimo
(Quinn “The Eskimo!”)
2
The easiest way to solve this problem is to change your C code to use void * for this untyped memory. For example:
// Assuming this new C declaration:
int write_message_data2(
model_struct *model,
void * message_data,
size_t message_data_size
);
// here’s how to call it from Swift:
var d: Data = …
let result = d.withUnsafeMutableBytes { buf in
write_message_data2(model, buf.baseAddress!, buf.count)
}
Note that the force unwrap is safe as long as d is not empty.
If you can’t do that then you need some type conversions:
let result = d.withUnsafeMutableBytes { buf in
write_message_data(model, buf.baseAddress!.assumingMemoryBound(to: UInt8.self), Int32(buf.count))
}
Two things to note here:
-
assumingMemoryBound(to:) is kinda suspect in general but it’s justified here because the data isn’t an array of UInt8 but rather untyped memory.
-
The conversion to Int32 could trap, which is why my first example used size_t.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
2 Likes