Convertir un UnsafePointer con longitud a un tipo Swift Array
arrays unsafe-pointers (2)
Simplemente puede inicializar un Swift Array
desde un UnsafeBufferPointer
:
func convert(length: Int, data: UnsafePointer<Int8>) -> [Int8] {
let buffer = UnsafeBufferPointer(start: data, count: length);
return Array(buffer)
}
Esto crea una matriz del tamaño necesario y copia los datos.
O como una función genérica:
func convert<T>(count: Int, data: UnsafePointer<T>) -> [T] {
let buffer = UnsafeBufferPointer(start: data, count: count);
return Array(buffer)
}
donde length
es la cantidad de elementos a los que apunta el puntero.
Si tiene un puntero UInt8
pero desea crear una matriz [T]
partir de los datos apuntados a, esta es una posible solución:
// 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)
}
donde length
ahora es el número de bytes . Ejemplo:
let arr = convert(12, data: ptr, Float.self)
crearía una matriz de 3 Float
a partir de los 12 bytes a los que apunta ptr
.
Estoy buscando las formas más sencillas de lograr una interoperabilidad C razonable en Swift, y mi bloque actual está convirtiendo un UnsafePointer<Int8>
(que era un const char *
), en una matriz [Int8]
.
Actualmente, tengo un algoritmo ingenuo que puede tomar un UnsafePointer
y un número de bytes y lo convierte en una matriz, elemento por elemento:
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])
}
}
El bucle en sí puede acelerarse utilizando arr.reserveCapacity(length)
, sin embargo, eso no elimina el problema del bucle en sí.
Soy consciente de esta pregunta SO que cubre cómo convertir UnsafePointer<Int8>
a String
, sin embargo, String
es una bestia completamente diferente a [T]
. ¿Existe una forma Swift conveniente de copiar bytes de longitud desde un UnsafePointer<T>
a una [T]
? Prefiero los métodos Swift puros, sin pasar por NSData
o similar. Si el algoritmo anterior es realmente la única forma de hacerlo, estoy feliz de seguir con eso.
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
}
}
Puede convertir los datos de la fila a bytes (Uint8)
Copia la extensión y úsala.