2017-08-08 67 views
1

有些情況下,您必須處理特定類型的結構,但上游API要求您通過指向其他地方的另一種類型的指針來呈現它。在Swift中重新解釋實體的正確方法是什麼?

例如,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中重新解釋結構的規範方法是什麼?

回答

2

你的第一種方法是正確的,使用withUnsafePointer()withMemoryRebound(),作爲一個可從各種例子見 在UnsafeRawPointer Migration提供,例如

在斯威夫特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()傳入構造,但可能是 臨時存儲的地址,並沒有保證 它仍然是有效的,當構造函數返回和閉合 被調用。

相關問題