将C字符串数组转换为Swift字符串数组

7
在Swift 3中,具有签名const char *f()的C函数被映射到导入时的UnsafePointer<Int8>! f()。它的结果可以转换为Swift字符串,如下所示:
let swiftString = String(cString: f())

问题是,如何将以NULL结尾的C字符串数组映射到Swift字符串数组?
原始的C签名:
const char **f()

导入的 Swift 签名:

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

Swift字符串数组:

let stringArray: [String] = ???
1个回答

14

据我所知,Swift中没有内置的方法。您需要遍历返回的指针数组,将C字符串转换为Swift String,直到找到一个nil指针:

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)
}
注意: Swift 3使用可选指针来表示可以为nil的指针。在您的情况下,f()返回一个隐式解包的可选值,因为头文件未经“审核”:编译器不知道该函数是否会返回null。 使用“nullability annotations”,您可以向Swift编译器提供该信息。
const char * _Nullable * _Nullable f(void);
// Imported to Swift  as
public func f() -> UnsafeMutablePointer<UnsafePointer<Int8>?>?

如果函数可以返回NULL,那么

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

如果f()保证返回非NULL结果。

有关空指针注释的更多信息,请参见Swift博客中的Nullability and Objective-C


在其他支持“真正”的String类型的语言(包括C++)中,需要非常相似的技术。这些“其他”语言中的每一种都为每个字符串值维护单独的“长度”:它们不依赖于终止的空字节。但是,它们都有专门设计用于处理它们的方法。(通常,它们在存储当前值的末尾保留已知的NULL字节。) - Mike Robinson
当涉及到数字计算机时,我从不说“永远不会发生”。如果它是一个指针,它可能是NULL。任何未来在f()中产生此返回值的错误都将演变成一个非常恶心且难以定位的错误,浪费了本应该节省微秒的时间,因此我是一个非常保守的编码人员... - Mike Robinson
@MikeRobinson:我添加这个注释不是为了“刮微秒”,而是为了引起对可空性注释的关注。当然,可以讨论一个已经记录返回有效指针的API的返回值是否应该在每次调用时进行检查,或者是否认为这是编程错误并应尽早崩溃。 - Martin R
@Uncommon:你在使用哪个Xcode版本?我这里还是可以编译的。 - Martin R
我正在使用Xcode 8.2.1。可能是因为我正在使用稍微不同的类型进行工作。 - Uncommon
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接