2015-09-16 20 views
19

Swift'de makul C birlikte işlerliği elde etmenin en kolay yollarını arıyorum ve şu anki blok UnsafePointer<Int8> (const char * olan) bir [Int8] dizisine dönüştürülüyor. Döngü kendisi arr.reserveCapacity(length) kullanılarak hızlandırılabilirBir UnsafePointer uzunluğunu Swift Array türüne dönüştürme

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]) 
    } 
} 

:

Şu anda, eleman tarafından naif bir UnsafePointer ve kaç bayt olacağı almak ve bir dizi dönüştürür olabilir algoritması öğesi Ancak, bu, döngü sorununu ortadan kaldırmaz.

Ben ancak String farklı bir canavar [T] tamamen olduğunu String için UnsafePointer<Int8> dönüştürmek için nasıl kapsayan this SO question farkındayım. UnsafePointer<T>'dan uzunluk baytlarını [T]'a kopyalamanın kullanışlı bir Swift yolu var mı? NSData ya da benzerlerinden geçmeden saf Swift yöntemlerini tercih ederim. Yukarıdaki algoritma gerçekten bunu yapmanın tek yolu ise, buna bağlı kaldığım için mutluyum.

cevap

30

Sadece bir UnsafeBufferPointer bir Swift Array başlatabilir: Bu gerekli büyüklük ve kopya veri dizisi oluşturur

func convert(length: Int, data: UnsafePointer<Int8>) -> [Int8] { 

    let buffer = UnsafeBufferPointer(start: data, count: length); 
    return Array(buffer) 
} 

.

Veya genel bir fonksiyonu olarak

:

length öğelerin sayısı o işaretçi noktaları etmektir
func convert<T>(count: Int, data: UnsafePointer<T>) -> [T] { 

    let buffer = UnsafeBufferPointer(start: data, count: count); 
    return Array(buffer) 
} 

.

Bir UInt8 işaretçi var ama bir [T] dizi oluşturmak istiyorsanız sivri-veri, o zaman bu olası bir çözümdür: length şimdi bayt sayısıdır

// 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) 
} 

. Örnek:

let arr = convert(12, data: ptr, Float.self) 

12 bayt 3 Float lik bir dizi oluşturacak ptr tarafından işaret.

+0

bu bellek sızıntısına neden olur mu? "UnsafeBufferPointer" ın belleğini boşaltacağına dair hiçbir belirti bulamıyorum. – Alexander

+0

@AMomchilov: 'UnsafeBufferPointer 'sadece bir işaretçidir, belleği ayırmaz, bu nedenle ücretsiz bir şey yoktur. Array, daha sonra Swift tarafından yönetilir. –

+0

Evet, ancak işaretçinin 'dönüşüme' geçmesi gerekiyor, doğru mu? Bu açık bir şekilde yapılmalıdır, IMO – Alexander

1
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 
    } 
} 

Sen byts (Uint8)

Kopya Uzantısı'na satır veri dönüştürmek ve kullanabilirsiniz ..

+0

Bu delicesine yardımcıdır. Benim C <-> Swift interop anksiyete sadece eriyor. – dugla

+0

Bunu duymak güzel –

İlgili konular