programing

길이가 있는 안전하지 않은 포인터를 Swift Array 유형으로 변환

megabox 2023. 9. 26. 22:14
반응형

길이가 있는 안전하지 않은 포인터를 Swift Array 유형으로 변환

저는 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), 그러나 그렇다고 해서 루프 자체의 문제가 제거되는 것은 아닙니다.

변환 방법에 대한 SO 질문에 대해 알고 있습니다.UnsafePointer<Int8>로.String,하지만String완전히 다른 짐승입니다.[T]. a에서 swift 길이 바이트를 복사하는 편리한 방법이 있습니까?UnsafePointer<T>[T]? 저는 통과하지 않고 순수한 스위프트 방식을 선호합니다.NSData또는 유사한.만약 위의 알고리즘이 정말로 유일한 방법이라면, 저는 기꺼이 그것을 고수할 것입니다.

간단히 스위프트를 초기화할 수 있습니다.Array로부터UnsafeBufferPointer:

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포인터가 가리키는 항목 수입니다.

만약 당신이.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) 
}

어디에lengthnow는 바이트 수입니다.예:

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

3개의 배열을 만들 겁니다Floats가 가리키는 12바이트에서 sptr.

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

행 데이터를 바이트(Uint8)로 변환할 수 있습니다.

확장명 복사 후 사용..

Array init 기능을 사용할 수도 있습니다.

init(unsafeUninitializedCapacity: Int, initializingWith initializer: (inout UnsafeMutableBufferPointer<Element>, inout Int) throws -> Void) rethrows

먼저 필요한 경우 안전하지 않은 RawPointer를 안전하지 않은 포인터로 변환한 다음 포인터를 버퍼 포인터로 변환하고 마지막으로 버퍼 포인터를 배열로 변환합니다.

예제, 안전하지 않은 RawPoint가 있다고 가정(dataPtr) 및 크기(dataSize)

let numberOfItems = dataSize / MemoryLayout<MyClass>.stride

let myArray = dataPtr.withMemoryRebound(to: MyClass.self,
                                        capacity: numberOfItems) { typedPtr in
    // Convert pointer to buffer pointer to access buffer via indices
    let bufferPointer = UnsafeBufferPointer(start: typedPtr, count: numberOfItems)
    // Construct array
    return [MyClass](unsafeUninitializedCapacity: numberOfItems) { arrayBuffer, count in
        count = numberOfItems
        for i in 0..<count {
            arrayBuffer[i] = bufferPointer[i]
        }
    }
}

언급URL : https://stackoverflow.com/questions/32606989/converting-an-unsafepointer-with-length-to-a-swift-array-type

반응형