Je cherche les moyens les plus simples pour obtenir une interopérabilité C raisonnable dans Swift, et mon bloc actuel convertit un UnsafePointer<Int8>
(Qui était un const char *
), En un tableau [Int8]
.
Actuellement, j'ai un algorithme naïf qui peut prendre un UnsafePointer
et un certain nombre d'octets et le convertit en tableau, élément par élément:
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])
}
}
La boucle elle-même peut être accélérée en utilisant arr.reserveCapacity(length)
, mais cela ne supprime pas le problème de la boucle elle-même.
Je connais cette SO question qui explique comment convertir UnsafePointer<Int8>
En String
, cependant String
est une bête complètement différente de [T]
. Existe-t-il une manière pratique Swift de copier des octets de longueur d'un UnsafePointer<T>
dans un [T]
? I Je préférerais les méthodes Swift, sans passer par NSData
ou similaire. Si l'algorithme ci-dessus est vraiment la seule façon de le faire, je suis heureux de m'en tenir à cela.
Vous pouvez simplement initialiser un Swift Array
à partir d'un UnsafeBufferPointer
:
func convert(length: Int, data: UnsafePointer<Int8>) -> [Int8] {
let buffer = UnsafeBufferPointer(start: data, count: length);
return Array(buffer)
}
Cela crée un tableau de la taille requise et copie les données.
Ou comme fonction générique:
func convert<T>(count: Int, data: UnsafePointer<T>) -> [T] {
let buffer = UnsafeBufferPointer(start: data, count: count);
return Array(buffer)
}
où length
est le nombre de items vers lequel pointe le pointeur.
Si tu as un UInt8
pointeur mais souhaitez créer un [T]
tableau à partir des données pointées, voici une solution possible:
// 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)
}
où length
est maintenant le nombre de octets. Exemple:
let arr = convert(12, data: ptr, Float.self)
créerait un tableau de 3 Float
s à partir des 12 octets pointés par ptr
.
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
}
}
Vous pouvez convertir des données de ligne en octets (Uint8)
Copiez l'extension et utilisez-la ..