简体   繁体   English

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

[英]A function to convert a C char array to a String

The statfs struct in C has these char array members: C语言中的statfs结构具有以下char数组成员:

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

The Swift type for these arrays in the Darwin.sys.mount module is a tuple with 90 elements: 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)

Another question about Converting a C char array to a String has an answer with code that I use twice in this example: 关于将C char数组转换为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)")
    }
}

To avoid repeating the code twice, I refactored the conversion code into the function below, but passing &vol.f_mntonname to it won't compile, and I can't see a way to fix the problem by using a different type for the first argument. 为了避免重复两次代码,我将转换代码重构到下面的函数中,但是将&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

The compiler complains about call to charArrayToString : 编译器抱怨调用charArrayToString
Cannot convert value of type ' (Int8, Int8, Int8) ' to expected argument type ' Int8 ' 无法将类型(Int8, Int8, Int8) '的值转换为预期的参数类型' Int8 '

It also complains when I pass a instead of &a : 当我通过a而不是&a时,它也会抱怨:
Cannot convert value of type ' (Int8, Int8, Int8) ' to expected argument type ' UnsafePointer<Int8> ' 无法将类型(Int8, Int8, Int8) '的值转换为预期的参数类型' UnsafePointer<Int8> '

You are trying to pass a pointer to a tuple as a point to a Int8 . 您正在尝试将指向元组的指针传递给Int8 Instead you need to pass a pointer to the first element of the tuple. 相反,您需要将指针传递给元组的第一个元素。 For example define the function: 例如定义函数:

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

(This function is adapted from and example in Apple's UnsafeRawPointer Migration ). (此功能改编自Apple的UnsafeRawPointer Migration中的示例 )。 Use this in your code to shorten your two let 's passing a pointer to the first tuple element: 使用这个在你的代码,以缩短你的两个let的一个指针传递给第一个元组元素:

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

However, despite that following the code in Apple's document it seems a bit overkill, you can also just: 但是,尽管遵循Apple文档中的代码似乎有点过大,但您也可以:

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

(All code tested using Xcode 8.2.1.) (所有代码均使用Xcode 8.2.1进行了测试。)

HTH 高温超导

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM