在Swift中转换为不同的C struct unsafe指针

Rob*_*b N 3 unsafe-pointers swift swift3

我想调用Posix套接字函数socketbindSwift.socket很容易 - 它需要Int32s,但是bind导致问题,因为我有一个sockaddr_in指针,但它需要一个sockaddr指针.在C中,这将是一个演员,如:

bind(sock, (struct sockaddr *)&sockAddress, sizeof(sockAddress))
Run Code Online (Sandbox Code Playgroud)

这是Swift的一次尝试:

let sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
var sockAddress = sockaddr_in()        
bind(sock, &sockAddress, UInt32(MemoryLayout<sockaddr_in>.size))
Run Code Online (Sandbox Code Playgroud)

bind行无法编译:无法将'sockaddr_in'类型的值转换为预期的参数类型'sockaddr'

如何投射指针?

OOP*_*Per 7

你可以写这样的东西:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
    sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1) {sockaddrPtr in
        bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
    }
}
Run Code Online (Sandbox Code Playgroud)

或者有人建议这可能会更好:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
    let sockaddrPtr = UnsafeRawPointer(sockaddrInPtr).assumingMemoryBound(to: sockaddr.self)
    bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
}
Run Code Online (Sandbox Code Playgroud)

这篇文章可能会有所帮助.


(UPDATE)如在描述的由马丁·r所示链路,现在MemoryLayout<T>.strideMemoryLayout<T>.size返回相同的值,其是一个用C的一致sizeof,其中T是一个导入C-结构.我会stride在这里保留我的答案版本,但现在这不是"必需".