在Swift中重新解释实体的正确方法是什么

在Swift中重新解释实体的正确方法是什么

本文介绍了在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 examplesprovided in UnsafeRawPointer Migration, e.g.

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 tothe constructor of UnsafeMutablePointer(), but that may bethe address of temporary storage, and there is no guarantee thatit is still valid when the constructor has returned and the closureis called.

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

08-20 08:53