我有一个 Swift 程序,可以与 C 库进行互操作。此 C 库返回一个内部包含 char[]
数组的结构,如下所示:
struct record
{
char name[8];
};
定义已正确导入到 Swift 中。但是,该字段被解释为 8 个 Int8
元素的元组(类型为 (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
),我不知道如何使用 Swift 将其转换为 String
。
没有接受 Int8
元组的 String
初始值设定项,并且似乎不可能获取指向元组第一个元素的指针(因为类型可以是异构的,这并不奇怪)。
现在,我最好的想法是创建一个微型 C 函数,它接受指向结构本身的指针,并将 name
作为 char*
指针而不是数组返回,然后就这样。
但是,有没有纯粹的 Swift 方法来做到这一点?
最佳答案
C 数组 char name[8]
作为元组导入到 Swift:
(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
name
的地址与name[0]
的地址相同,并且
Swift 保留从 C 导入的结构的内存布局,如
confirmed by Apple engineer Joe Groff:
... You can leave the struct defined in C and import it into Swift. Swift will respect C's layout.
因此,我们可以传递record.name
的地址,
转换为 UInt8
指针,以
字符串初始值设定项。以下代码已针对 Swift 4.2 及更高版本进行了更新:
let record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(to: record.name) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
String(cString: $0)
}
}
注意:假设name[]
中的字节是有效的以NUL结尾的UTF-8序列。
对于旧版本的 Swift:
// Swift 2:
var record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(&record.name) {
String.fromCString(UnsafePointer($0))!
}
// Swift 3:
var record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(to: &record.name) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: record.name)) {
String(cString: $0)
}
}
关于arrays - 将 C 字符数组转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57550733/