【问题标题】:Interoperating with C pointer to an Int array in Swift在 Swift 中与指向 Int 数组的 C 指针进行互操作
【发布时间】:2016-06-23 17:39:46
【问题描述】:

我有一个带有此功能的旧代码库:

-(void)foo: (int *)buffer {
  myArray[0] = buffer[0];
  myArray[1] = buffer[1];
  myArray[2] = buffer[2];
  myArray[3] = buffer[3];
}

在 Swift 中,这个方法是这样写的:

func foo(buffer: UnsafeMutablePointer<Int32>) {
}

int 指针现在被视为UnsafeMutablePointer&lt;UInt32&gt;。我无法在 Swift 中访问 buffer 的下标;即我不能像这样打电话给buffer[0]

func foo(buffer: UnsafeMutablePointer<Int32>) {
  myArray[0] = buffer[0] // won't compile, buffer treated as Int32
}

出于绝望,即使知道UnsafeMutablePointer&lt;Int32&gt; 在Swift 中最终被解析为Int32 类型,我也尝试了以下方法:

guard let buffer = buffer.memory as? [Int] else { fatalError() }

guard let buffer = buffer as? [Int] else { fatalError() }

guard let buffer = buffer.memory as? [Int32] else { fatalError() }

guard let buffer = buffer as? [Int32] else { fatalError() }

有人能给我指出正确的方向,让我了解如何像 Objective-C 代码那样访问下标成员吗?

【问题讨论】:

标签: swift


【解决方案1】:

你想多了:

class MyClass {
    var myArray = [Int32](count: 4, repeatedValue: 0)

    func foo(buffer: UnsafeMutablePointer<Int32>) {
        for i in 0..<4 {
            myArray[i] = buffer[i]
        }
    }
}

您可以将myArray 更改为[Int32] 以使其匹配buffer。或者您可以将buffer 转换为Int

myArray[i] = Int(buffer[i])

【讨论】:

  • 谢谢,我确实想多了;为了将来参考他人,UnsafeMutablePointer&lt;Int32&gt; 允许下标。
  • 附带说明,我很好奇为什么guard let buffer = buffer.memory as? [Int32] else { fatalError() } 会失败。对此有什么想法吗?
  • memory 指向数组的第一个元素,而不是数组本身,因此不可转换
  • guard let buffer = buffer as? [Int32] else { ... } 怎么样?
  • 没有意识到UnsafeMutablePointer 是可下标的,很高兴知道。一般不喜欢这种方法,因为有一种更简洁的内置方法可以做到这一点
【解决方案2】:

UnsafePointer 用于对内存中的单个位置进行建模。要处理缓冲区,请使用UnsafeBufferPointer

UnsafeBufferPointer 可以像Array 一样下标,并且具有绑定检查(因为它需要您给它一个count)。

您甚至不必像在 Objective C 代码中那样进行手动转换,您可以直接从 UnsafeBufferPointer 初始化 Array,非常简单:

func foo(buffer: UnsafeMutablePointer<Int32>) {
    myArray = Array(UnsafeBufferPointer(start: pointer, count: 4))
}

这个解决方案甚至是通用的:UnsafeBufferPointer 可以从您提供的 UnsafePointer 推断其类型,并将该信息传递给 Array,使其自动创建一个 [Int32]

注意:记得释放你的 UnsafePointer!

【讨论】:

  • 谢谢。真的很酷的方法。我确认这也有效。请问您是否知道安全找到countUnsafeMutablePointer&lt;Int32&gt; 的方法?
  • 不,这太“低级”了。 UnsafeMutablePointer 只知道地址和类型。它无法知道长度,这就是你必须提供它的原因。如果您正在处理 C 字符串,则可以迭代查找第一个 NUL 字符。除此之外,没有办法知道
  • 你可以从任何给你指针的来源获得长度。
【解决方案3】:

也许你改用UnsafeBufferPointer

http://swiftdoc.org/v2.2/type/UnsafeBufferPointer/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 2017-11-06
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多