Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inter-operability of Swift arrays with C?

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)

?

like image 733
hotpaw2 Avatar asked Jun 07 '14 18:06

hotpaw2


People also ask

Which one is faster array or set in Swift?

Array is faster than set in terms of initialization. Set is slower than an array in terms of initialization because it uses a hash process. The array allows to store duplicate elements in it. Set doesn't allow to store duplicate elements in it.

What is the datatype of array in Swift?

The type of a Swift array is written in full as Array<Element> , where Element is the type of values the array is allowed to store. You can also write the type of an array in shorthand form as [Element] .

Can array have different data types in Swift?

Swift Array – With Elements of Different TypesIn Swift, we can define an array that can store elements of any type. These are also called Heterogenous Collections. To define an array that can store elements of any type, specify the type of array variable as [Any].

How do arrays work in Swift?

In Swift, each element in an array is associated with a number. The number is known as an array index. In the above example, we have created an array named languages . Here, we can see each array element is associated with the index number.


3 Answers

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
}
like image 194
Sulthan Avatar answered Oct 09 '22 13:10

Sulthan


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))
like image 11
hotpaw2 Avatar answered Oct 09 '22 14:10

hotpaw2


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
}
like image 10
yglixm Avatar answered Oct 09 '22 13:10

yglixm