Inter-operability of Swift arrays with C?
Solution 1
I don't think this is easily possible. In the same way as you can't use C style arrays for parameters working with a NSArray
.
All C arrays in Swift are represented by an UnsafePointer
, e.g. UnsafePointer<Float>
. Swift doesn't really know that the data are an array. If you want to convert them into a Swift array, you will have create a new object and copy the items there one by one.
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)
Edit
Just found a better solution, this could actually avoid copying.
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
}
Solution 2
As of Beta 5, one can just use pass &array The following example passes 2 float arrays to a vDSP C function:
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))
Solution 3
The withUnsafePointerToElements()
method was removed, now you can use the withUnsafeBufferPointer()
instead, and use the baseAddress
method in the block to achieve the point
let array: Array<Float> = [10.0, 50.0, 40.0]
array.withUnsafeBufferPointer { (cArray: UnsafePointer<Float>) -> () in
cArray.baseAddress
}
Related videos on Youtube
hotpaw2
Ronald Nicholson, founder, developer, Mail Clerk, and Assistant Cat Herder at HotPaw Productions, making iPhone/iOS apps since the App store first opened. iOS app development and audio/DSP consulting. Formerly an ASIC chip manager/architect/designer.
Updated on June 21, 2022Comments
-
hotpaw2 almost 2 years
How can one pass or copy the data in a C array, such as
float foo[1024];
, between C and Swift functions that use fixed size arrays, such as declared by
let foo = Float[](count: 1024, repeatedValue: 0.0)
?
-
Abhi Beckert over 9 yearsHow about an example that doesn't show real world code? It's not very clear which parts are what you're trying to demonstrate and which are just part of the C API you're using.
-
jhabbott about 9 yearsSurely the array with unsafe pointer must copy the contents, as it doesn't know how long it will stay allocated?
-
Ephemera over 8 years@jhabbott That's why it's "unsafe" :). Depending on the internal representation of Array<> it may have to perform a copy to a contiguous memory area if it doesn't already exist in one, but this is probably reasonably unlikely/infrequent in practice.
-
marchinram over 8 yearsLooks like
withUnsafePointerToElements
was removed: developer.apple.com/library/mac/releasenotes/General/… -
Cameron Lowell Palmer about 8 years@AbhiBeckert DSPSplitComplex is a part of the Apple Accelerate framework which is a C API and is a good example. It is a simple struct for holding a vector of complex numbers.
-
Nicolas Buquet over 7 yearsAs of Swift 3, Array init is now:
var myRealArray = [Float](repeating: 0.0, count: len)
-
tatiana_c about 7 yearsU saved my life