将C char数组转换为String的函数

时间:2017-01-20 06:25:04

标签: arrays tuples interop swift3.0.2

C中的statfs结构具有这些char数组成员:

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

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

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

关于Converting a C char array to a String的另一个问题有一个代码的答案,我在这个例子中使用了两次:

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>

1 个答案:

答案 0 :(得分:1)

您正在尝试将指针传递给元组作为指向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进行测试。)

HTH