Hi All.
When interfacing with C, Swift does some magic to auto-convert Swift strings to
char *. This is great, but passing an array of string pointers gets much more
involved. The type translates to UnsafePointer<UnsafePointer<CChar>> in Swift.
So I originally tried to get pointers to the individual strings by using
cString(using:), and putting them into an Array, but then I found out that
there is nothing holding on to the cStrings, so they go away before they can be
used. I finally wound up with this hack:
public extension Array {
public func cStringArray() throws -> ArrayBridge<Element,CChar> {
return try ArrayBridge<Element,CChar>(array:self) {
guard let item = $0 as? String,
let translated = item.cString(using: .utf8) else {
throw hexdreamsCocoa.Errors.InvalidArgumentError
}
return translated
}
}
}
/*
We need to have this intermediate object around to hold on to the translated
objects, otherwise they will go away.
The UnsafePointer won't hold on to the objects that it's pointing to.
*/
public struct ArrayBridge<SwiftType,CType> {
let originals :[SwiftType]
let translated :[[CType]]
let pointers :[UnsafePointer<CType>?]
public let pointer :UnsafePointer<UnsafePointer<CType>?>
init(array :[SwiftType], transform: (SwiftType) throws -> [CType]) throws {
self.originals = array
self.translated = try array.map(transform)
var pointers = [UnsafePointer<CType>?]()
for item in translated {
pointers.append(UnsafePointer<CType>(item))
}
pointers.append(nil)
self.pointers = pointers
self.pointer = UnsafePointer(self.pointers)
}
}
And then to use it you would do something like
try stringArray.cStringArray().pointer
This all seems pretty ugly. So my question is: Is this the right way to handle
this problem? Is there a simpler way? It would be awesome if Swift
auto-converted arrays of Strings to const char * const *, since it’s a
construct used so much in C.
Thanks!
-Kenny
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users