将C char数组转换为String

zne*_*eak 22 arrays interop tuples swift

我有一个与C库互操作的Swift程序.这个C库返回一个char[]内部有数组的结构,如下所示:

struct record
{
    char name[8];
};
Run Code Online (Sandbox Code Playgroud)

该定义被正确导入Swift.但是,该字段被解释为8个元素(类型)的元组,我不知道如何使用Swift 转换为a .Int8(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)String

没有String接受Int8元组的初始化器,并且似乎不可能获得指向元组的第一个元素的指针(因为类型可以是异构的,这并不奇怪).

现在,我最好的想法是创建一个微小的C函数,它接受一个指向结构本身的指针,并name作为char*指针而不是数组返回,并继续使用它.

然而,是否有纯粹的Swift方式呢?

Mar*_*n R 26

C数组char name[8]作为元组导入Swift:

(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
Run Code Online (Sandbox Code Playgroud)

地址与地址name相同name[0],Swift 保留从C导入的结构的内存布局, Apple工程师Joe Groff证实:

...您可以保留在C中定义的结构并将其导入Swift.斯威夫特将尊重C的布局.

因此,我们可以将record.name转换为UInt8指针的地址传递给String初始值设定项:

var record = someFunctionReturningAStructRecord()

// Swift 2:
let name = withUnsafePointer(&record.name) {
    String.fromCString(UnsafePointer($0))!
}

// Swift 3:
let name = withUnsafePointer(to: &record.name) {
    $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: record.name)) {
        String(cString: $0)
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:假设字节name[]是有效的NUL终止的UTF-8序列.