swift unsafe-pointers

swift - ¿Cómo obtener bytes de un UnsafeMutableRawPointer?



unsafe-pointers (4)

Cómo se accede a los bytes (o Int16''s, flotadores, etc.) de la memoria apuntada por un UnsafeMutableRawPointer (nuevo en Swift 3) entregado a una función Swift por una API de C (Core Audio, etc.)


Aquí está la documentación de la API de conversión no segura [mutable] RawPointer a T / no segura [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

y luego de Unsafe[MutablePointer]<T> a T se puede convertir con pointee y 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


Aquí hay un ejemplo de Swift 4 de convertir una matriz UInt8 literal en un UnsafeMutableRawPointer y volver a una matriz 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) }


Crear objeto de datos .

init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Data.Deallocator)

Una forma importante que falta en las otras respuestas aquí es inicializar un objeto de datos con UnsafeMutableRawPointer. El objeto de datos se puede utilizar para otros cálculos.

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 }


load<T> lee bytes sin procesar de la memoria y construye un valor de tipo T :

let ptr = ... // Unsafe[Mutable]RawPointer let i16 = ptr.load(as: UInt16.self)

opcionalmente en un byte offset:

let i16 = ptr.load(fromByteOffset: 4, as: UInt16.self)

También está assumingMemoryBound() que se convierte de un Unsafe[Mutable]RawPointer a un Unsafe[Mutable]Pointer<T> , suponiendo que la memoria apuntada contiene un valor de tipo T:

let i16 = ptr.assumingMemoryBound(to: UInt16.self).pointee

Para una matriz de valores puede crear un "puntero de búfer":

let i16bufptr = UnsafeBufferPointer(start: ptr.assumingMemoryBound(to: UInt16.self), count: count)

Un puntero de búfer ya podría ser suficiente para su propósito, es un subíndice y puede ser enumerado de manera similar a una matriz. Si es necesario, crea una matriz desde el puntero del búfer:

let i16array = Array(i16bufptr)

Como dijo @Hamish, se puede encontrar más información y detalles en