如何在Swift 3.0或更高版本中将UnsafeMutableRawPointer!转换为UnsafeMutablePointer <Float>?

9
我正在使用Accelerate库开发我的iOS应用程序。几年前,我用Swift 2.0构建了这个应用程序,它一直运行良好。现在Swift已经更新到3.0和4.0,我必须将大部分代码转换为当前语法。我已经运行了转换器,但仍然存在一些语法错误。这是我最难解决的问题之一。我似乎找不到一个同样简洁的方法来解决它。
我为图像的基本算术操作编写了函数之一如下:
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
}

Image 有一个字段 buffer,它是一个 vImage_Buffer,定义如下:

open class Image {

open var buffer: vImage_Buffer

....}
问题: 调用buffer.data返回UnsafeMutableRawPointer!类型。函数vDSP_add需要UnsafeMutablePointer<Float>类型参数。我曾经可以立即将其转换为UnsafeMutablePointer<Float>对象。看起来现在这个初始化器已经不推荐使用了。因此,在像let leftOperand = UnsafeMutablePointer<Float>(left.buffer.data)这样的代码中,我会得到以下错误
Cannot invoke initializer for type 'UnsafeMutablePointer<Float>' with an argument list of type '(UnsafeMutableRawPointer!)'.

我不知道是否在这里忽略了一些非常简单的东西,但我仍然没有解决这个问题。但是,我正在寻找一种解决方案,它不需要使用循环手动复制每个元素,因为该函数在应用程序中被频繁调用。
以下是一些可能有帮助的文档链接:

提前感谢您!

2个回答

19

使用assumingMemoryBound(to:)函数:

返回一个指向该指针引用的内存的类型化指针,假设该内存已经绑定为指定类型。

在你的情况下:

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

请查看 UnsafeRawPointer 迁移指南 了解更多信息。


1
我认为这可能解决问题。至少,我不会得到编译器错误。我会在其他错误修复后尽快更新。谢谢! - Keen R.D.
@KeenR.D.:有进展了吗?如果需要更多信息,请告诉我。 - Martin R
谢谢您的跟进。我已经完成了所有的转换。但是,我仍在努力解决这个代码签名问题。一旦解决了,我会及时通知您更新情况。 - Keen R.D.
我又让应用程序运行起来了,你的解决方案很有效!再次感谢你! - Keen R.D.

0

我以前也遇到过同样的问题。

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
}

1
谢谢您的建议!data本身是一个指针,因为它是vImage_buffer的一部分。我尝试将其转换为Float时出现了错误。似乎assumingMemoryBound(to:)对我有用。 - Keen R.D.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接