【问题标题】:What is the correct way to reinterpret an entity in Swift?在 Swift 中重新解释实体的正确方法是什么?
【发布时间】:2017-08-08 07:00:02
【问题描述】:

在某些情况下,您必须处理某种类型的结构,但上游 API 要求您通过指向其他地方的另一种类型的指针来呈现它。

例如,Unix Bind 期望它的第二个参数是指向 sockaddr 的指针,而构造函数应该是 sockaddr_in

现在我坚持使用两层with*

var sa = sockaddr_in(/* ... */)

withUnsafePointer(to: &sa) { _sa in
  _sa.withMemoryRebound(to: sockaddr.self, capacity: 1) { __sa in
    let err = bind(fd, __sa, socklen_t(saSize))
    precondition(err == 0)
  }
}

但是,我对这种方法的嘈杂感到沮丧。当我在指针类型之间使用unsafeBitCast 时:

bind(fd, unsafeBitCast(__sa, to: UnsafeMutablePointer<sockaddr>.self), socklen_t(saSize))

然后编译器警告我不要这样做,并建议求助于withMemoryRebound

当我使用就地构造的指针时:

UnsafeMutablePointer(mutating: &sa).withMemoryRebound(to: sockaddr.self, capacity: 1) { _sa in
  let err = bind(fd, _sa, socklen_t(saSize))
  precondition(err == 0)
}

然后它和初始版本一样工作,并且摆脱了一层嵌套。虽然它看起来比with* 更脆弱。也不清楚,如果就地指针是正确的方法,为什么withUnsafePointer 甚至存在。

话虽如此,在 Swift 中重新解释结构的规范方法是什么?

【问题讨论】:

    标签: swift swift3 unsafe-pointers


    【解决方案1】:

    你的第一个方法是正确的,使用withUnsafePointer()withMemoryRebound(),从各种示例中可以看出 在UnsafeRawPointer Migration 中提供,例如

    在 Swift 3 中,用户应该明确地将内存重新绑定到不同的 类型:

    let result = withUnsafePointer(to: &addr) {
      // Temporarily bind the memory at &addr to a single instance of type sockaddr.
      $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
        connect(sock, $0, socklen_t(MemoryLayout<sockaddr_in>.stride))
      }
    }
    

    另一种方法

    UnsafeMutablePointer(mutating: &sa).withMemoryRebound(...) { ... }
    

    在我看来很脆弱。 sa 作为 inout 参数传递给 UnsafeMutablePointer() 的构造函数,但 可能 是 临时存储的地址,并不能保证 当构造函数返回并且闭包时它仍然有效 叫做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多