如何从 UnsafeMutableRawPointer 中获取字节?
How to get bytes out of an UnsafeMutableRawPointer?
如何访问由 C Swift 函数传递给 UnsafeMutableRawPointer(Swift 3 中的新功能)指向的内存不足的字节(或 Int16、浮点数等) =12=](核心音频等)
load<T>
从内存中读取原始字节并构造一个 T
:
类型的值
let ptr = ... // Unsafe[Mutable]RawPointer
let i16 = ptr.load(as: UInt16.self)
可选的字节偏移量:
let i16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
还有 assumingMemoryBound()
将 Unsafe[Mutable]RawPointer
转换为 Unsafe[Mutable]Pointer<T>
,假设指向的内存包含类型 T:
的值
let i16 = ptr.assumingMemoryBound(to: UInt16.self).pointee
对于值数组,您可以创建 "buffer pointer":
let i16bufptr = UnsafeBufferPointer(start: ptr.assumingMemoryBound(to: UInt16.self), count: count)
一个缓冲区指针可能已经足够满足你的需要了,它
是可订阅的,可以像数组一样被枚举。
如有必要,从缓冲区指针创建一个数组:
let i16array = Array(i16bufptr)
正如@Hamish 所说,可以在
找到更多信息和详细信息
这里是 api Unsafe[Mutable]RawPointer 到 T/Unsafe[MutablePointer] 转换的文档:
/// Binds the allocated memory to type `T` and returns an
/// `UnsafePointer<T>` to the bound memory at `self`.
///
/// - Precondition: The memory is uninitialized.
/// - Postcondition: The memory is bound to 'T' starting at `self` continuing
/// through `self` + `count` * `MemoryLayout<T>.stride`
/// - Warning: Binding memory to a type is potentially undefined if the
/// memory is ever accessed as an unrelated type.
public func bindMemory<T>(to type: T.Type, capacity count: Int) -> UnsafePointer<T>
/// Converts from an `UnsafeRawPointer` to UnsafePointer<T> given that
/// the region of memory starting at `self` is already bound to type `T`.
///
/// - Precondition: The memory is bound to 'T' starting at `self` for some
/// unspecified capacity.
///
/// - Warning: Accessing memory via the returned pointer is undefined if the
/// if the memory has not been bound to `T`.
public func assumingMemoryBound<T>(to: T.Type) -> UnsafePointer<T>
/// Reads raw bytes from memory at `self + offset` and constructs a
/// value of type `T`.
///
/// - Precondition: The underlying pointer plus `offset` is properly
/// aligned for accessing `T`.
///
/// - Precondition: The memory is initialized to a value of some type, `U`,
/// such that `T` is layout compatible with `U`.
public func load<T>(fromByteOffset offset: Int = default, as type: T.Type) -> T
然后从 Unsafe[MutablePointer]<T>
到 T
可以转换为
pointee
和 move
apis
/// Accesses the `Pointee` instance referenced by `self`.
///
/// - Precondition: the pointee has been initialized with an instance of
/// type `Pointee`.
public var pointee: Pointee { get }
/// Retrieves the `pointee`, returning the referenced memory to an
/// uninitialized state.
///
/// Equivalent to `{ defer { deinitialize() }; return pointee }()`, but
/// more efficient.
///
/// - Precondition: The pointee is initialized.
///
/// - Postcondition: The memory is uninitialized.
public func move() -> Pointee
创建数据对象。
init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Data.Deallocator)
此处其他答案中缺少的一个重要方法是使用 UnsafeMutableRawPointer 初始化数据对象。该数据对象随后可用于其他计算。
public func base64(quality: Int32 = 67) -> String? {
var size: Int32 = 0
if let image = gdImageJpegPtr(internalImage, &size, quality) {
// gdImageJpegPtr returns an UnsafeMutableRawPointer that is converted to a Data object
let d = Data(bytesNoCopy: image, count: Int(size), deallocator: .none)
return d.base64EncodedString()
}
return nil
}
这是一个 Swift 4 示例,将文字 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)
}
如何访问由 C Swift 函数传递给 UnsafeMutableRawPointer(Swift 3 中的新功能)指向的内存不足的字节(或 Int16、浮点数等) =12=](核心音频等)
load<T>
从内存中读取原始字节并构造一个 T
:
let ptr = ... // Unsafe[Mutable]RawPointer
let i16 = ptr.load(as: UInt16.self)
可选的字节偏移量:
let i16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
还有 assumingMemoryBound()
将 Unsafe[Mutable]RawPointer
转换为 Unsafe[Mutable]Pointer<T>
,假设指向的内存包含类型 T:
let i16 = ptr.assumingMemoryBound(to: UInt16.self).pointee
对于值数组,您可以创建 "buffer pointer":
let i16bufptr = UnsafeBufferPointer(start: ptr.assumingMemoryBound(to: UInt16.self), count: count)
一个缓冲区指针可能已经足够满足你的需要了,它 是可订阅的,可以像数组一样被枚举。 如有必要,从缓冲区指针创建一个数组:
let i16array = Array(i16bufptr)
正如@Hamish 所说,可以在
找到更多信息和详细信息这里是 api Unsafe[Mutable]RawPointer 到 T/Unsafe[MutablePointer] 转换的文档:
/// Binds the allocated memory to type `T` and returns an
/// `UnsafePointer<T>` to the bound memory at `self`.
///
/// - Precondition: The memory is uninitialized.
/// - Postcondition: The memory is bound to 'T' starting at `self` continuing
/// through `self` + `count` * `MemoryLayout<T>.stride`
/// - Warning: Binding memory to a type is potentially undefined if the
/// memory is ever accessed as an unrelated type.
public func bindMemory<T>(to type: T.Type, capacity count: Int) -> UnsafePointer<T>
/// Converts from an `UnsafeRawPointer` to UnsafePointer<T> given that
/// the region of memory starting at `self` is already bound to type `T`.
///
/// - Precondition: The memory is bound to 'T' starting at `self` for some
/// unspecified capacity.
///
/// - Warning: Accessing memory via the returned pointer is undefined if the
/// if the memory has not been bound to `T`.
public func assumingMemoryBound<T>(to: T.Type) -> UnsafePointer<T>
/// Reads raw bytes from memory at `self + offset` and constructs a
/// value of type `T`.
///
/// - Precondition: The underlying pointer plus `offset` is properly
/// aligned for accessing `T`.
///
/// - Precondition: The memory is initialized to a value of some type, `U`,
/// such that `T` is layout compatible with `U`.
public func load<T>(fromByteOffset offset: Int = default, as type: T.Type) -> T
然后从 Unsafe[MutablePointer]<T>
到 T
可以转换为
pointee
和 move
apis
/// Accesses the `Pointee` instance referenced by `self`.
///
/// - Precondition: the pointee has been initialized with an instance of
/// type `Pointee`.
public var pointee: Pointee { get }
/// Retrieves the `pointee`, returning the referenced memory to an
/// uninitialized state.
///
/// Equivalent to `{ defer { deinitialize() }; return pointee }()`, but
/// more efficient.
///
/// - Precondition: The pointee is initialized.
///
/// - Postcondition: The memory is uninitialized.
public func move() -> Pointee
创建数据对象。
init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Data.Deallocator)
此处其他答案中缺少的一个重要方法是使用 UnsafeMutableRawPointer 初始化数据对象。该数据对象随后可用于其他计算。
public func base64(quality: Int32 = 67) -> String? {
var size: Int32 = 0
if let image = gdImageJpegPtr(internalImage, &size, quality) {
// gdImageJpegPtr returns an UnsafeMutableRawPointer that is converted to a Data object
let d = Data(bytesNoCopy: image, count: Int(size), deallocator: .none)
return d.base64EncodedString()
}
return nil
}
这是一个 Swift 4 示例,将文字 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)
}