Search code examples
iosswiftaccelerate-frameworkunsafemutablepointervimage

How to cast UnsafeMutableRawPointer! to UnsafeMutablePointer<Float> in Swift 3.0 or newer?


I am working with Accelerate library for my iOS app. I built this app in Swift 2.0 a couple years ago and it was working fine. Now that Swift is updated to 3.0 and 4.0, I have to convert most of the code to the current syntax. I have run the converter but I still have some syntax errors. This is the one that I am having trouble the most fixing. I couldn't seem to find an equivalently succinct way to fix it.

I made functions for basic arithmetic operation on images. This is one of them:

public func add(_ left: Image, right: Image) -> Image! {
    let results = Image.init(rows: left.size.rows, columns: left.size.columns, pixelSize: left.pixelSize)
    let leftOperand = UnsafeMutablePointer<Float>(left.buffer.data)
    let rightOperand = UnsafeMutablePointer<Float>(right.buffer.data)
    let destination = UnsafeMutablePointer<Float>(results.buffer.data)
    vDSP_vadd(leftOperand, 1, rightOperand, 1, destination, 1, UInt(left.lengthOfBuffer))
    return results
}

The class Image has a field buffer which is a vImage_Bufferand is defined like such,

open class Image {

open var buffer: vImage_Buffer

....}

The problem: Calling buffer.data returns a type of UnsafeMutableRawPointer!. The vDSP_add function requires UnsafeMutablePointer<Float> for its parameters. I used to be able to cast it to an UnsafeMutablePointer<Float> object right away. Looks like the initializer is deprecated now. Thus, on the codes like let leftOperand = UnsafeMutablePointer<Float>(left.buffer.data), I get this error

Cannot invoke initializer for type 'UnsafeMutablePointer<Float>' with an argument list of type '(UnsafeMutableRawPointer!)'.

I don't know if I overlook something very simple here, yet I still haven't fixed this. But, I am looking for a solution that doesn't require manually copying each element using a loop, since this function is called pretty frequently in the app.

Just some documentation links that might help:

Thank you in advance!


Solution

  • Use assumingMemoryBound(to:):

    Returns a typed pointer to the memory referenced by this pointer, assuming that the memory is already bound to the specified type.

    In your case:

    let leftOp = left.buffer.data.assumingMemoryBound(to: Float.self)
    let rightOp = right.buffer.data.assumingMemoryBound(to: Float.self)
    // ...
    

    See UnsafeRawPointer Migration for more information.