将具有length的UnsafePointer转换为Swift Array类型

Eph*_*era 27 c arrays unsafe-pointers swift

我正在寻找在Swift中实现合理的C互操作性的最简单方法,而我当前的块正在将UnsafePointer<Int8>(它是a const char *)转换为[Int8]数组.

目前,我有一个天真的算法,可以采用一个UnsafePointer和多个字节,并逐个元素地将其转换为数组:

func convert(length: Int, data: UnsafePointer<Int8>) {

    let buffer = UnsafeBufferPointer(start: data, count: length);
    var arr: [Int8] = [Int8]()
    for (var i = 0; i < length; i++) {
        arr.append(buffer[i])
    }
}
Run Code Online (Sandbox Code Playgroud)

循环本身可以通过使用来加速arr.reserveCapacity(length),但这不会消除循环本身的问题.

我知道这个SO问题涵盖了如何转换UnsafePointer<Int8>String,但String完全是一个不同的野兽[T].是否有一种方便的Swift方式将长度字节从一个复制UnsafePointer<T>到一个[T]?我更喜欢纯粹的Swift方法,而不是通过NSData或类似的.如果上述算法真的是唯一的方法,我很乐意坚持下去.

Mar*_*n R 42

您可以简单地Array从以下位置初始化Swift UnsafeBufferPointer:

func convert(length: Int, data: UnsafePointer<Int8>) -> [Int8] {

    let buffer = UnsafeBufferPointer(start: data, count: length);
    return Array(buffer)
}
Run Code Online (Sandbox Code Playgroud)

这将创建所需大小的数组并复制数据.

或者作为通用功能:

func convert<T>(count: Int, data: UnsafePointer<T>) -> [T] {

    let buffer = UnsafeBufferPointer(start: data, count: count);
    return Array(buffer) 
}
Run Code Online (Sandbox Code Playgroud)

指针指向length项目数在哪里.

如果你有一个UInt8指针,但想要[T]从指向数据创建一个数组,那么这是一个可能的解决方案:

// Swift 2:
func convert<T>(length: Int, data: UnsafePointer<UInt8>, _: T.Type) -> [T] {

    let buffer = UnsafeBufferPointer<T>(start: UnsafePointer(data), count: length/strideof(T));
    return Array(buffer) 
}

// Swift 3:
func convert<T>(length: Int, data: UnsafePointer<UInt8>, _: T.Type) -> [T] {
    let numItems = length/MemoryLayout<T>.stride
    let buffer = data.withMemoryRebound(to: T.self, capacity: numItems) {
        UnsafeBufferPointer(start: $0, count: numItems)
    }
    return Array(buffer) 
}
Run Code Online (Sandbox Code Playgroud)

其中length现在的数目的字节.例:

let arr  = convert(12, data: ptr, Float.self)
Run Code Online (Sandbox Code Playgroud)

将从Float指向的12个字节创建一个3 s 的数组ptr.