web-dev-qa-db-ja.com

長さのあるUnsafePointerをSwift配列型に変換する

私はSwiftで合理的なCの相互運用性を達成するための最も簡単な方法を探しています、そして私の現在のブロックは_UnsafePointer<Int8>_(これは_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])
    }
}
_

ループ自体はarr.reserveCapacity(length)を使用して高速化できますが、ループ自体の問題は取り除かれません。

this SO question を知っています。これは_UnsafePointer<Int8>_をStringに変換する方法をカバーしますが、Stringは_[T]_とは完全に異なる獣。便利なSwift長さバイトを_UnsafePointer<T>_から_[T]_にコピーする方法はありますか?純粋な= Swiftメソッド、NSDataなどを経由せずに。上記のアルゴリズムが本当にそれを行う唯一の方法である場合、私はそれを固く満足しています。

27
Ephemera

単純にSwift ArrayUnsafeBufferPointerから初期化できます:

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

    let buffer = UnsafeBufferPointer(start: data, count: length);
    return Array(buffer)
}

これにより、必要なサイズの配列が作成され、データがコピーされます。

または、汎用関数として:

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

    let buffer = UnsafeBufferPointer(start: data, count: count);
    return Array(buffer) 
}

ここで、lengthは、ポインターが指すitemsの数です。

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) 
}

ここで、length nowはbytesの数です。例:

let arr  = convert(12, data: ptr, Float.self)

Floatが指す12バイトから3つのptrsの配列を作成します。

42
Martin R
extension NSData {

    public func convertToBytes() -> [UInt8] {
        let count = self.length / sizeof(UInt8)
        var bytesArray = [UInt8](count: count, repeatedValue: 0)
        self.getBytes(&bytesArray, length:count * sizeof(UInt8))
        return bytesArray
    }
}

行データをbytsに変換できます(Uint8)

拡張機能をコピーして使用します。

1
tBug