问题描述
在某些情况下,您必须处理某种类型的结构,但是上游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中重新解释实体的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!