Inter-operability of Swift arrays with C?

前端 未结 4 1924
终归单人心
终归单人心 2021-02-02 09:46

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 d

相关标签:
4条回答
  • 2021-02-02 10:21

    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
    }
    
    0 讨论(0)
  • 2021-02-02 10:24

    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
    }
    
    0 讨论(0)
  • 2021-02-02 10:31

    let's see what Apple do:

    public struct float4 {
    
        public var x: Float
    
        public var y: Float
    
        public var z: Float
    
        public var w: Float
    
        /// Initialize to the zero vector.
        public init()
    
        /// Initialize a vector with the specified elements.
        public init(_ x: Float, _ y: Float, _ z: Float, _ w: Float)
    
        /// Initialize a vector with the specified elements.
        public init(x: Float, y: Float, z: Float, w: Float)
    
        /// Initialize to a vector with all elements equal to `scalar`.
        public init(_ scalar: Float)
    
        /// Initialize to a vector with elements taken from `array`.
        ///
        /// - Precondition: `array` must have exactly four elements.
        public init(_ array: [Float])
    
        /// Access individual elements of the vector via subscript.
        public subscript(index: Int) -> Float
    }
    
    0 讨论(0)
  • 2021-02-02 10:40

    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))
    
    0 讨论(0)
提交回复
热议问题