本文介绍了将 C 字符数组转换为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个与 C 库互操作的 Swift 程序.这个 C 库返回一个结构体,里面有一个 char[] 数组,像这样:

I have a Swift program that does interop with a C library. This C library returns a structure with a char[] array inside, like this:

struct record
{
    char name[8];
};

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

The definition is correctly imported into Swift. However, the field is interpreted as a tuple of 8 Int8 elements (typed (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)), which I have no idea how to transform into a String with Swift.

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

There is no String initializer that accepts an Int8 tuple, and it doesn't seem possible to get a pointer to the first element of the tuple (since types can be heterogenous, that's not really surprising).

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

Right now, my best idea is to create a tiny C function that accepts a pointer to the structure itself and return name as a char* pointer instead of an array, and go with that.

然而,有没有纯粹的 Swift 方式来做到这一点?

Is there, however, are pure Swift way to do it?

推荐答案

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

The C array char name[8] is imported to Swift as a tuple:

(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)

name的地址与name[0]的地址相同,并且Swift 保留从 C 导入的结构的内存布局,如由 Apple 工程师 Joe Groff 确认:

The address of name is the same as the address of name[0], andSwift preserves the memory layout of structures imported from C, asconfirmed by Apple engineer Joe Groff:

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

因此,我们可以传递record.name的地址,转换为 UInt8 指针,以字符串初始值设定项.以下代码已针对 Swift 4.2 及更高版本进行了更新:

As a consequence, we can pass the address of record.name,converted to an UInt8 pointer, tothe String initializer. The following code has been updated for Swift 4.2 and later:

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 序列.

NOTE: It is assumed that the bytes in name[] are a valid NUL-terminated UTF-8 sequence.

对于旧版本的 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)
    }
}

这篇关于将 C 字符数组转换为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-08 16:39