2014-06-07 185 views
25

如何可以一个Swift数组与C的互操作性?

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

通过或在C数组复制数据,如

float foo[1024]; 

,C和使用固定大小的数组夫特功能,如宣告之间?

回答

18

我不认为这很容易。与使用NSArray的参数不能使用C风格的数组一样。

Swift中的所有C数组都由UnsafePointer表示,例如, UnsafePointer<Float>。 Swift并不知道数据是一个数组。如果你想将它们转换成一个Swift数组,你将创建一个新的对象并将它们逐个复制。

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) 

编辑

刚刚发现一个更好的解决方案,这样做可能会避免复制。

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

当然,带有不安全指针m的数组ust复制内容,因为它不知道它将保持分配多久? – jhabbott

+0

@jhabbott这就是为什么它是“不安全的”:)。根据Array <>的内部表示形式,如果它不在一个存储区中,它可能必须执行到连续存储区的复制,但这在实践中可能不太合适/不经常发生。 – Ephemera

+2

看起来像'''withUnsafePointerToElements'''被删除:https://developer.apple.com/library/mac/releasenotes/General/APIDiffsMacOSX10_10_3/modules/Swift.html – marchinram

7

在Beta 5,一种可以只使用通过&阵列 下面的示例将2个浮阵列到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

如何处理一个例子不显示真实世界的代码?目前还不清楚哪些部分是您正在尝试演示的部分,哪些部分仅仅是您使用的C API的一部分。 –

+0

@AbhiBeckert DSPSplitComplex是Apple Accelerate框架的一部分,它是一个C API,是一个很好的例子。这是一个简单的结构,用于保存复数的向量。 –

+0

从Swift 3开始,Array init现在是:'var myRealArray = [Float](重复:0.0,count:len)' –

8

除去withUnsafePointerToElements()方法,现在则可以使用代替withUnsafeBufferPointer(),并使用块中的baseAddress方法实现该点

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