1

I'm trying to call the function DSPSplitComplex:

var real = [Float](input_windowed)
var imaginary = [Float](repeating: 0.0, count: input_windowed.count)
        
var splitComplex = DSPSplitComplex(realp: &real, imagp: &imaginary)        

but that gives the warning:

Cannot use inout expression here; argument 'realp' must be a pointer that outlives the call to 'init(realp:imagp:)'

so after that I tried:

var splitComplex = DSPSplitComplex(
    realp:  UnsafeMutablePointer(mutating: real),
    imagp:  UnsafeMutablePointer(mutating: imaginary) )

and that gives the warning:

Initialization of 'UnsafeMutablePointer<Float>' results in a dangling pointer

so finally I tried this:

var splitComplex =
    withUnsafeMutablePointer(to: &real) { realpPtr in
        withUnsafeMutablePointer(to: &imaginary) { imaginaryPtr in
            DSPSplitComplex(realp: realpPtr, imagp: imaginaryPtr)
    }
}

and that gives the following compile error:

Cannot convert value of type 'UnsafeMutablePointer<[Float]>' to expected argument type 'UnsafeMutablePointer<Float>'

What is the correct way to call this function (and similar functions in the Accelerate framework) ?

pnadeau
  • 427
  • 5
  • 8

1 Answers1

0

You are very close. You just need a buffer pointer rather than a pointer to the array:

real.withUnsafeMutableBufferPointer { realp in
    imaginary.withUnsafeMutableBufferPointer { imagp in

        var splitComplex = DSPSplitComplex(realp: realp.baseAddress!, 
                                           imagp: imagp.baseAddress!)

        // ...
    }
}

Note the BufferPointer part of the calls.

For a full example, see Apple's FFT sample.

The key point of this syntax rather than your original approach is that it ensures that real and imaginary continue to exist for the lifetime of the pointers. In your original code, the arrays can be deallocated on the very next line, making splitComplex hold dangling pointers.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks for that. Any idea why they chose this naming convention, I mean the `Buffer` part of it? – pnadeau Feb 11 '23 at 23:02
  • 1
    A buffer in Swift is a typed pointer to contiguous storage, plus a capacity. That's what Arrays offer as an interface. The function (rather than an Array method) you used, withUnsafeMutablePointer, provides a pointer to the actual Array data structure itself, not its storage. Arrays in Swift are not like in C. They are not just "a pointer to contiguous memory." Their contents may not even be contiguous. Also, they carry metadata; most significantly the length. So a pointer to "the Array data structure itself" is almost never what you would want. – Rob Napier Feb 12 '23 at 00:19