char ** in Swift
A "string" in C is just a continuous chunk of char values in memory with
\0 at the end. To reference it, a variable of type char * is used to store
the address of the first char (commonly known as a pointer 😉). It's common
to have string manipulating functions take this form:
void foo(char **errorMessage) {
// ...
}
To mutate the arugment errorMessage of type char *, foo takes a pointer
to it, (char *)*.
How do we call foo in Swift?
Here's the tl;dr. We can wrap it in a Swift function that have the same interface:
func fooSwift(inout errorMessage: String?) {
var message: UnsafeMutablePointer<CChar> = nil
foo(&message)
errorMessage = String.fromCString(message)
}
errorMessage will contain whatever our C function foo assigns to it.
So, what's really going on here?
Inspecting foo's signature in Swift, we see
func foo(errorMessage: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>)
… okey, errorMessage's type is little intimidating to someone who doesn't
use C functions in Swift everyday (like me)!
Let's break it down. Swift does a ton of work for us to interoperate with C:
-
CCharis Swift's name forcharin C (shocking, amiright?) -
UnsafeMutablePointer<Type>roughly translates toType *, so syntactically, we can see whyUnsafeMutablePointer<UnsafeMutablePointer<CChar>>is used to bridge the C type(char *)*. -
A function that takes
UnsafeMutablePointer<Type>argument acceptsinout Typevalues. Therefore, we can look atfooasfoo(inout errorMessage: UnsafeMutablePointer<CChar>) -
Swift acknowledge C's string representation and provides convenient methods for converting
char */UnsafeMutablePointer<CChar>to its ownStringtype (String.fromCString()).
Hopefully you can see how fooSwift works now.
Taking a step back, to deal with char ** in Swift, we overcame 2 obstacles:
-
The difference in string representation between C and Swift.
-
Compared to C pointers, Swift's
inoutexpresses mutability of function arguments in a more restricted way. We can't nestinouts to represent the infinite layers of indirections that pointers achieve.