0

C 中的statfsstruct 具有以下char数组成员:

char f_mntonname[MNAMELEN];    /* directory on which mounted */
char f_mntfromname[MNAMELEN];  /* mounted file system */

模块中这些数组的 Swift 类型Darwin.sys.mount是一个包含 90 个元素的元组:

public var f_mntonname: (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8,
                         ...
                         Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)

另一个关于将 C char 数组转换为字符串的问题有一个答案,我在这个例子中使用了两次代码:

import Darwin.sys.mount
var vols: UnsafeMutablePointer<statfs>?
let count = getmntinfo(&vols, 0)    
if let volsarray = vols, count > 0 {
    for i in 0 ..< count {
        var vol = volsarray[Int(i)]
        let mntOnName = withUnsafePointer(to: &vol.f_mntonname) {
            $0.withMemoryRebound(to: UInt8.self,
                                 capacity: MemoryLayout.size(ofValue: vol.f_mntonname)) {
                String(cString: $0)
            }
        }
        let mntFromName = withUnsafePointer(to: &vol.f_mntfromname) {
            $0.withMemoryRebound(to: UInt8.self,
                                 capacity: MemoryLayout.size(ofValue: vol.f_mntfromname)) {
                String(cString: $0)
            }
        }
        print("on \(mntOnName)  from \(mntFromName)")
    }
}

为了避免重复代码两次,我将转换代码重构为下面的函数,但传递&vol.f_mntonname给它不会编译,而且我看不到通过对第一个参数使用不同类型来解决问题的方法。

func charArrayToString(_ array: UnsafePointer<Int8>, capacity: Int) -> String {
    return array.withMemoryRebound(to: UInt8.self, capacity: capacity) {
        String(cString: $0)
    }
}

var a = (Int8(65), Int8(66), Int8(67))
print(charArrayToString(&a, capacity: 3)) // doesn't compile

编译器抱怨调用charArrayToString
    无法将类型“ (Int8, Int8, Int8)”的值转换为预期的参数类型“ Int8

当我通过a而不是时它也会抱怨&a
    无法将类型' (Int8, Int8, Int8)'的值转换为预期的参数类型' UnsafePointer<Int8>'

4

1 回答 1

2

您正在尝试将指向元组的指针作为指向 a 的点传递Int8。相反,您需要将指针传递给元组的第一个元素。例如定义函数:

func charPointerToString(_ pointer: UnsafePointer<Int8>) -> String
{
   return String(cString: UnsafeRawPointer(pointer).assumingMemoryBound(to: CChar.self))
}

(此函数改编自 Apple 的UnsafeRawPointer Migration中的示例)。在您的代码中使用它来缩短您的两个let传递指向第一个元组元素的指针:

let mntOnName = charPointerToString(&vol.f_mntonname.0)
let mntFromName = charPointerToString(&vol.f_mntfromname.0)

但是,尽管遵循 Apple 文档中的代码似乎有点矫枉过正,但您也可以:

let mntOnName = String(cString: &vol.f_mntonname.0)
let mntFromName = String(cString: &vol.f_mntfromname.0)

(所有代码均使用 Xcode 8.2.1 进行测试。)

高温高压

于 2017-01-20T21:01:06.733 回答