Here's how we do it for internal testing purposes: withArrayOfCStrings 
<https://github.com/apple/swift/blob/dfc3933a05264c0c19f7cd43ea0dca351f53ed48/stdlib/private/SwiftPrivate/SwiftPrivate.swift#L68>.
 The callback is great because you don't have to worry about lifetimes.

Jordan

> On Aug 18, 2016, at 13:04, Kenny Leung via swift-users 
> <[email protected]> wrote:
> 
> 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

_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to