2017-08-08 12 views
1

特定の型の構造体を扱う必要がある場合がありますが、上流のAPIでは他の場所の別の型へのポインタを使用してそれを提示する必要があります。Swiftでエンティティを再解析する正しい方法は何ですか?

たとえば、Unix Bindは、2番目の引数が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) 
} 

を次に、それは最初のバージョンと同様に動作し、ネスティング1つのレベルを私たちにのRID。それはwith*よりも虚弱に見えますが。また、インプレースポインタが正しいアプローチである場合は、なぜwithUnsafePointerが存在するのかも不明です。

Swiftの構造を再解析するための正式な方法は何ですか?

答えて

2

一つは、例えば、UnsafeRawPointer Migrationで提供される様々な例 から見ることができるようにあなたの第1の方法は、withUnsafePointer() withMemoryRebound()とを使用して、正しいものです

スウィフト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(...) { ... } 

は私に壊れやすい見えます。 saUnsafeMutablePointer()のコンストラクタにinoutパラメータとして渡され、それ一時的な記憶のアドレス であってもよく、コンストラクタが戻ってきたと閉鎖 が呼び出されたとき、それはまだ有効である という保証はありません。

関連する問題