arrays - 将 C 字符数组转换为字符串

标签 arrays swift interop tuples

我有一个与 C 库互操作的 Swift 程序。这个 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/27455773/

相关文章:

ios - 在扩展中声明属性并出现错误的访问错误

d3.js - dartlang interop js 和 d3 集成在 dart 中不起作用

c# - 如何将 wchar_t* 从 C++ 编码到 C# 作为输出参数或返回值?

c - 在 C 中使用指针提取数组的一部分

javascript - Rx js过滤器方法不返回过滤器数组

c - 将 2D 数组传递给函数 : zero-value and print issue

ios - Swift-Firebase 多个观察者

java - 如何使用第一维作为流的键将二维数组映射到 HashMap

ios - 从侧边栏菜单在 UIWebView 中加载错误的 url

C# 在 Word 文档中查找和替换文本的替代方法