在Swift中重新解释实体的正确方法是什么? [英] What is the correct way to reinterpret an entity in Swift?

查看:98
本文介绍了在Swift中重新解释实体的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

There are cases when you have to deal with a structure of certain type, but the upstream API requires you to present it though a pointer to another type at other places.

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

For instance, Unix Bind is expecting its second argument to be a pointer to a sockaddr, whereas the constructor should be sockaddr_in.

目前,我坚持使用两层with*:

For now I'm sticking to a two-layer 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时:

However, I'm discouraged by noisiness of this approach. When I use unsafeBitCast between pointer types:

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

然后,编译器警告我不要这样做,并建议您使用withMemoryRebound.

Then the compiler warns me not to do so, and recommends resort to withMemoryRebound.

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

When I use an in-place constructed pointer:

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

然后它和初始版本一样好,使我们摆脱了一层嵌套.尽管它看起来比with*更脆弱.同样不清楚的是,如果就地指针是正确的方法,为什么withUnsafePointer甚至存在.

Then it works as well as the initial version, and rids us of one level of nesting. Although it looks more frail than with*. Also it's unclear, if the in-place pointer is the correct approach, why withUnsafePointer even exists.

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

Having that said, what is the canonical way to reinterpret a structure in Swift?

推荐答案

您的第一个方法是正确的方法,使用withUnsafePointer()withMemoryRebound(),正如从各种示例中可以看到的 在 UnsafeRawPointer迁移,例如

Your first method is the correct one, using withUnsafePointer() and withMemoryRebound(), as one can see from the various examples provided in UnsafeRawPointer Migration, e.g.

在Swift 3中,用户应显式将内存重新绑定到其他 类型:

In Swift 3, the user should explicitly rebind memory to a different type:

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()的构造函数,但是可能是 临时存储的地址,并且不能保证 当构造函数返回并关闭时,它仍然有效 叫做.

looks fragile to me. sa is passed as an inout parameter to the constructor of UnsafeMutablePointer(), but that may be the address of temporary storage, and there is no guarantee that it is still valid when the constructor has returned and the closure is called.

这篇关于在Swift中重新解释实体的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆