When one wants to call C APIs that use C strings, it looks natural to use String.utf8CString, which returns a "contiguously stored null-terminated UTF-8 representation of the string".
String.utf8CString returns ContiguousArray<CChar>. CChar is documented to be signed or unsigned, depending on the platform:
This will be the same as either CSignedChar (in the common case) or CUnsignedChar, depending on the platform.
However, C apis that use strings are imported into Swift as consuming Int8. For example, the following function is imported as (UnsafePointer<Int8>?) -> Int32:
int cFunc(const char *inStr);
It appears that we have a mismatch. A platform-dependent CChar on one side, and a constant Int8 on the other side. But maybe this Int8 is just a CChar in disguise? Maybe it could be imported as UInt8 on other platforms? In this case, there would not be any mismatch, but just the illusion of a mismatch. I don't know.
Which one of the versions below is platform-independent?
// Version 1
string.utf8CString.withUnsafeBufferPointer { buffer in // CChar
buffer.withMemoryRebound(to: Int8.self) { buffer in // Int8
cFunc(buffer.baseAddress!)
}
}
// Version 2
string.utf8CString.withUnsafeBufferPointer { buffer in // CChar
cFunc(buffer.baseAddress!)
}
jrose
(Jordan Rose)
2
Yes, this is correct. Maybe we should change the importer to preserve "CChar" even though we don't preserve any of the other C types (CInt, CUnsignedLong), just because of the weirdness around signed/unsigned char.
4 Likes
Thanks Jordan and Ben, both for removing any shadow of a doubt, and for wondering if something could be improved here. I added to SR-466 a link to this thread. Have a nice day :-)
jrose
(Jordan Rose)
5
I looked into how much work this would be and it's not a lot! So I tagged it as a starter bug.
1 Like