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

2

9

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!

Backman answered 2/5, 2018 at 11:0 Comment(0)
O
19

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.

Otis answered 2/5, 2018 at 11:9 Comment(4)
I think this might solve the problem. At least, I don't get a compiler error. I will give an update as soon as I've got the other errors fixed. Thank you!Backman
@KeenR.D.: Any progress? Let me know if you need more information.Otis
thank you for following up. I got all of the conversion done. But, I am still trying to figure out this code signing problem. Once it got resolved, I’ll keep you updated.Backman
I have got the app running again. Your solution works! Thank you again!Backman
N
0

I used to have the same problem.

public func add(_ left: Image, right: Image) -> Image! {
let results = Image.init(rows: left.size.rows, columns: left.size.columns, pixelSize: left.pixelSize)
var leftOperand = Float(left.buffer.data)
var rightOperand = Float(right.buffer.data)
var destination = Float(results.buffer.data)
vDSP_vadd(&leftOperand, 1, &rightOperand, 1, &destination, 1, UInt(left.lengthOfBuffer))
return results
}
Nitrobacteria answered 2/5, 2018 at 13:35 Comment(1)
Thank you for your suggestion! The data itself is a pointer since it is part of the vImage_buffer. I got an error trying to cast it into a Float. Seems like assumingMemoryBound(to:): might work for me.Backman

© 2022 - 2024 — McMap. All rights reserved.