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!

David H
  • 40,852
  • 12
  • 92
  • 138
Keen R.D.
  • 123
  • 1
  • 5

2 Answers2

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.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    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! – Keen R.D. May 02 '18 at 13:49
  • @KeenR.D.: Any progress? Let me know if you need more information. – Martin R May 07 '18 at 11:39
  • 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. – Keen R.D. May 07 '18 at 14:11
  • I have got the app running again. Your solution works! Thank you again! – Keen R.D. May 11 '18 at 06:12
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
}
Enea Dume
  • 3,014
  • 3
  • 21
  • 36
  • 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. – Keen R.D. May 02 '18 at 13:52