How to use UnsafeMutableRawPointer to fill an array?

First, let's assume you have a UnsafeRawPointer and a length:

let ptr: UnsafeRawPointer = ...
let length: Int = ...

Now you want to convert that to an [float4]. First, you can convert your UnsafeRawPointer to a typed pointer by binding it to a type:

let float4Ptr = ptr.bindMemory(to: float4.self, capacity: length)

Now you can convert that to a typed buffer pointer:

let float4Buffer = UnsafeBufferPointer(start: float4Ptr, count: length)

And since a buffer is a collection, you can initialize an array with it:

let output = Array(float4Buffer)

For much more on working with UnsafeRawPointer, see SE-0138, SE-0107, and the UnsafeRawPointer Migration Guide.


To complement @VasilyBodnarchuk's answer:

extension UnsafeMutableRawPointer {
    func toArray<T>(to type: T.Type, capacity count: Int) -> [T] {
        return Array(UnsafeBufferPointer(start: bindMemory(to: type, capacity: count), count: count))
    }
}

Details

  • Xcode 11.2.1 (11B500), Swift 5.1

Solution

extension UnsafeMutableRawPointer {
    func toArray<T>(to type: T.Type, capacity count: Int) -> [T]{
        let pointer = bindMemory(to: type, capacity: count)
        return Array(UnsafeBufferPointer(start: pointer, count: count))
    }
}

Usage

var array = [1,2,3,4,5]
let ponter = UnsafeMutableRawPointer(mutating: array)
print(ponter.toArray(to: Int.self, capacity: array.count))

Another option is to create an array of the appropriate size and pass the address to the underlying storage to the function:

var pixelData = Array(repeating: float4(), count: myTextureSizeInFloat4)
pixelData.withUnsafeMutableBytes {
    texture.getBytes($0.baseAddress!, ...)
}

Inside the closure, $0 is a UnsafeMutableRawBufferPointer representing the array storage as a collection of bytes, and $0.baseAddress is a pointer to the first byte.

Tags:

Swift

Metal