2014-06-07 11 views
25

Come si può passare o copiare i dati in una matrice C, comeInteroperabilità di array Swift con C?

float foo[1024]; 

, tra C e funzioni Swift che utilizzano matrici fissate dimensioni come dichiarata dal

let foo = Float[](count: 1024, repeatedValue: 0.0) 

?

risposta

18

Non penso che sia facilmente possibile. Allo stesso modo in cui non è possibile utilizzare gli array in stile C per i parametri che funzionano con un NSArray.

Tutti i array C in Swift sono rappresentati da un UnsafePointer, ad es. UnsafePointer<Float>. Swift in realtà non sa che i dati sono una matrice. Se vuoi convertirli in un array Swift, avrai creato un nuovo oggetto e copieresti gli elementi uno per uno.

let array: Array<Float> = [10.0, 50.0, 40.0] 

// I am not sure if alloc(array.count) or alloc(array.count * sizeof(Float)) 
var cArray: UnsafePointer<Float> = UnsafePointer<Float>.alloc(array.count) 
cArray.initializeFrom(array) 

cArray.dealloc(array.count) 

Modifica

appena trovato una soluzione migliore, questo potrebbe effettivamente evitare di copiare.

let array: Array<Float> = [10.0, 50.0, 40.0] 

// .withUnsafePointerToElements in Swift 2.x 
array.withUnsafeBufferPointer() { (cArray: UnsafePointer<Float>) ->() in 
    // do something with the C array 
} 
+0

Sicuramente la matrice con m pericoloso puntatore ust copiare il contenuto, in quanto non sa quanto a lungo rimarrà assegnato? – jhabbott

+0

@jhabbott Ecco perché è "non sicuro" :). A seconda della rappresentazione interna di Array <> potrebbe essere necessario eseguire una copia in un'area di memoria contigua se non esiste già in uno, ma questo è probabilmente ragionevolmente improbabile/raro nella pratica. – Ephemera

+2

Sembra che '' 'withUnsafePointerToElements''' sia stato rimosso: https://developer.apple.com/library/mac/releasenotes/General/APIDiffsMacOSX10_10_3/modules/Swift.html – marchinram

7

Al Beta 5, si può semplicemente utilizzare passare & matrice Il seguente esempio passa 2 allineamenti galleggiante a una funzione VDSP C:

let logLen = 10 
let len = Int(pow(2.0, Double(logLen))) 
let setup : COpaquePointer = vDSP_create_fftsetup(vDSP_Length(logLen), FFTRadix(kFFTRadix2)) 

var myRealArray = [Float](count: len, repeatedValue: 0.0) 
var myImagArray = [Float](count: len, repeatedValue: 0.0) 
var cplxData = DSPSplitComplex(realp: &myRealArray, imagp: &myImagArray) 

vDSP_fft_zip(setup, &cplxData, 1, vDSP_Length(logLen),FFTDirection(kFFTDirection_Forward)) 
+9

Che ne dici di un esempio che non mostrare codice del mondo reale? Non è molto chiaro quali parti sono ciò che stai cercando di dimostrare e quali sono solo parte dell'API C che stai utilizzando. –

+0

@AbhiBeckert DSPSplitComplex è una parte del framework Apple Accelerate che è un'API C ed è un buon esempio. È una semplice struttura per contenere un vettore di numeri complessi. –

+0

A partire da Swift 3, l'init di array ora è: 'var myRealArray = [Float] (ripetendo: 0.0, count: len)' –

8

stato rimosso Procedimento withUnsafePointerToElements(), ora è possibile utilizzare la withUnsafeBufferPointer() invece, e utilizzare il metodo baseAddress nel blocco per raggiungere il punto

let array: Array<Float> = [10.0, 50.0, 40.0] 
array.withUnsafeBufferPointer { (cArray: UnsafePointer<Float>) ->() in 
    cArray.baseAddress 
}