Zmey
Zmey

Reputation: 2539

Converting array of C strings to Swift string array

In Swift 3, C function with signature const char *f() is mapped to UnsafePointer<Int8>! f() on import. It's result can be converted to a Swift string as:

let swiftString = String(cString: f())

The question is, how a NULL terminated C array of C strings can be mapped to Swift array of strings?

The original C signature:

const char **f()

Imported Swift signature:

UnsafeMutablePointer<UnsafePointer<Int8>?>! f()

Swift array of strings:

let stringArray: [String] = ???

Upvotes: 7

Views: 1245

Answers (1)

Martin R
Martin R

Reputation: 539685

There is no built-in method as far as I know. You have to iterate over the returned pointer array, converting C strings to Swift Strings, until a nil pointer is found:

if var ptr = f() {
    var strings: [String] = []
    while let s = ptr.pointee {
        strings.append(String(cString: s))
        ptr += 1
    }
    // Now p.pointee == nil.

    print(strings)
}

Remark: Swift 3 uses optional pointers for pointers that can be nil. In your case, f() returns an implicitly unwrapped optional because the header file is not "audited": The compiler does not know whether the function can return NULL or not.

Using the "nullability annotations" you can provide that information to the Swift compiler:

const char * _Nullable * _Nullable f(void);
// Imported to Swift  as
public func f() -> UnsafeMutablePointer<UnsafePointer<Int8>?>?

if the function can return NULL, and

const char * _Nullable * _Nonnull f(void);
// Imported to Swift  as
public func f() -> UnsafeMutablePointer<UnsafePointer<Int8>?>

if f() is guaranteed to return a non-NULL result.

For more information about the nullability annotations, see for example Nullability and Objective-C in the Swift blog.

Upvotes: 14

Related Questions