I noticed some unusual behaviour when working with a C library which took strings in as const char *
(which is converted to Swift as UnsafePointer
As mentioned in the comments, this is a clear bug in Swift.
Here's a workaround I'm using. If you can't trust Swift to convert the strings to pointers for you, then you've got to do it yourself.
Assuming C function defined as:
void multiString(const char *arg0, const char *arg1, const char *arg2);
Swift code:
func callCFunction(arg0: String?, arg1: String?, arg2: String?) {
let dArg0 = arg0?.data(using: .utf8) as NSData?
let pArg0 = dArg0?.bytes.assumingMemoryBound(to: Int8.self)
let dArg1 = arg1?.data(using: .utf8) as NSData?
let pArg1 = dArg1?.bytes.assumingMemoryBound(to: Int8.self)
let dArg2 = arg2?.data(using: .utf8) as NSData?
let pArg2 = dArg2?.bytes.assumingMemoryBound(to: Int8.self)
multiString(pArg1, pArg2, pArg3)
}
Warning:
Don't be tempted to put this in a function like:
/* DO NOT USE -- BAD CODE */
func ocstr(_ str: String?) -> UnsafePointer? {
guard let str = str else {
return nil
}
let nsd = str.data(using: .utf8)! as NSData
//This pointer is invalid on return:
return nsd.bytes.assumingMemoryBound(to: Int8.self)
}
which would remove repeated code. This doesn't work because the data object nsd
gets deallocated at the end of the function. The pointer is therefore not valid on return.