如何使用 UnsafeMutableRawPointer 填充数组?
How to use UnsafeMutableRawPointer to fill an array?
我有一个金属纹理,我想通过将其设为 float4 数组来从 Swift 访问它的数据(这样我就可以访问每个像素的 4 个颜色分量)。
我发现了 MTLTexture
的这个方法:
getBytes(UnsafeMutableRawPointer, bytesPerRow: Int, bytesPerImage: Int, from: MTLRegion, mipmapLevel: Int, slice: Int)
我完全不知道如何使用 UnsafeMutableRawPointer,它是如何工作的,以及如何将数据返回到一个简单的 Swift 数组中。
我的第一次尝试是创建一个指针并像那样分配足够的 space,但我什至不知道我是否应该这样做:
var pointer = UnsafeMutableRawPointer.allocate(bytes: myTextureSizeInBytes, alignedTo: 0)
然后我完全不知道如何将这些数据返回到标准 Swift 数组中...
谢谢。
首先,假设您有一个 UnsafeRawPointer
和一个长度:
let ptr: UnsafeRawPointer = ...
let length: Int = ...
现在您想将其转换为 [float4]
。首先,您可以通过将 UnsafeRawPointer
绑定到类型来将其转换为类型化指针:
let float4Ptr = ptr.bindMemory(to: float4.self, capacity: length)
现在您可以将其转换为类型化缓冲区指针:
let float4Buffer = UnsafeBufferPointer(start: float4Ptr, count: length)
并且由于缓冲区是一个集合,您可以用它来初始化数组:
let output = Array(float4Buffer)
有关使用 UnsafeRawPointer
的更多信息,请参阅 SE-0138, SE-0107, and the UnsafeRawPointer Migration Guide。
另一种选择是创建一个适当大小的数组
并将底层存储的地址传递给函数:
var pixelData = Array(repeating: float4(), count: myTextureSizeInFloat4)
pixelData.withUnsafeMutableBytes {
texture.getBytes([=10=].baseAddress!, ...)
}
在闭包内部,[=11=]
是一个 UnsafeMutableRawBufferPointer
将数组存储表示为字节集合,以及
[=13=].baseAddress
是指向第一个字节的指针。
这是一个 Swift4 示例,将文字 UInt8 数组转换为 UnsafeMutableRawPointer 并返回到 UInt32 数组
static func unsafePointerTest() {
//let a : [UInt8] = [0,0,0,4,0,0,0,8,0,0,0,12]
let a : [UInt8] = [0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00] //little endian
//0xFF, 0xF0, 0xF0, 0x12] //317780223 = 12F0F0FF
let b:UnsafeMutableRawPointer = UnsafeMutableRawPointer(mutating:a)
let bTypedPtr = b.bindMemory(to: UInt32.self, capacity: a.count/4)
let UInt32Buffer = UnsafeBufferPointer(start: bTypedPtr, count: a.count/4)
let output = Array(UInt32Buffer)
print(output)
}
详情
- Xcode 11.2.1 (11B500), Swift 5.1
解决方案
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))
}
}
用法
var array = [1,2,3,4,5]
let ponter = UnsafeMutableRawPointer(mutating: array)
print(ponter.toArray(to: Int.self, capacity: array.count))
补充@VasilyBodnarchuk 的回答:
extension UnsafeMutableRawPointer {
func toArray<T>(to type: T.Type, capacity count: Int) -> [T] {
return Array(UnsafeBufferPointer(start: bindMemory(to: type, capacity: count), count: count))
}
}
我有一个金属纹理,我想通过将其设为 float4 数组来从 Swift 访问它的数据(这样我就可以访问每个像素的 4 个颜色分量)。
我发现了 MTLTexture
的这个方法:
getBytes(UnsafeMutableRawPointer, bytesPerRow: Int, bytesPerImage: Int, from: MTLRegion, mipmapLevel: Int, slice: Int)
我完全不知道如何使用 UnsafeMutableRawPointer,它是如何工作的,以及如何将数据返回到一个简单的 Swift 数组中。
我的第一次尝试是创建一个指针并像那样分配足够的 space,但我什至不知道我是否应该这样做:
var pointer = UnsafeMutableRawPointer.allocate(bytes: myTextureSizeInBytes, alignedTo: 0)
然后我完全不知道如何将这些数据返回到标准 Swift 数组中...
谢谢。
首先,假设您有一个 UnsafeRawPointer
和一个长度:
let ptr: UnsafeRawPointer = ...
let length: Int = ...
现在您想将其转换为 [float4]
。首先,您可以通过将 UnsafeRawPointer
绑定到类型来将其转换为类型化指针:
let float4Ptr = ptr.bindMemory(to: float4.self, capacity: length)
现在您可以将其转换为类型化缓冲区指针:
let float4Buffer = UnsafeBufferPointer(start: float4Ptr, count: length)
并且由于缓冲区是一个集合,您可以用它来初始化数组:
let output = Array(float4Buffer)
有关使用 UnsafeRawPointer
的更多信息,请参阅 SE-0138, SE-0107, and the UnsafeRawPointer Migration Guide。
另一种选择是创建一个适当大小的数组 并将底层存储的地址传递给函数:
var pixelData = Array(repeating: float4(), count: myTextureSizeInFloat4)
pixelData.withUnsafeMutableBytes {
texture.getBytes([=10=].baseAddress!, ...)
}
在闭包内部,[=11=]
是一个 UnsafeMutableRawBufferPointer
将数组存储表示为字节集合,以及
[=13=].baseAddress
是指向第一个字节的指针。
这是一个 Swift4 示例,将文字 UInt8 数组转换为 UnsafeMutableRawPointer 并返回到 UInt32 数组
static func unsafePointerTest() {
//let a : [UInt8] = [0,0,0,4,0,0,0,8,0,0,0,12]
let a : [UInt8] = [0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00] //little endian
//0xFF, 0xF0, 0xF0, 0x12] //317780223 = 12F0F0FF
let b:UnsafeMutableRawPointer = UnsafeMutableRawPointer(mutating:a)
let bTypedPtr = b.bindMemory(to: UInt32.self, capacity: a.count/4)
let UInt32Buffer = UnsafeBufferPointer(start: bTypedPtr, count: a.count/4)
let output = Array(UInt32Buffer)
print(output)
}
详情
- Xcode 11.2.1 (11B500), Swift 5.1
解决方案
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))
}
}
用法
var array = [1,2,3,4,5]
let ponter = UnsafeMutableRawPointer(mutating: array)
print(ponter.toArray(to: Int.self, capacity: array.count))
补充@VasilyBodnarchuk 的回答:
extension UnsafeMutableRawPointer {
func toArray<T>(to type: T.Type, capacity count: Int) -> [T] {
return Array(UnsafeBufferPointer(start: bindMemory(to: type, capacity: count), count: count))
}
}