Rob N Rob N - 3 months ago 68
Swift Question

Cast to different C struct unsafe pointer in Swift

I want to call the Posix socket functions

socket
and
bind
from Swift.
socket
is pretty easy—it takes
Int32
s, but
bind
is causing a problem, because I have a
sockaddr_in
pointer, but it wants a
sockaddr
pointer. In C, this would be a cast, like:

bind(sock, (struct sockaddr *)&sockAddress, sizeof(sockAddress))


Here's an attempt in Swift:

let sock: Int32 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
var sockAddress: sockaddr_in = sockaddr_in()
memset(&sockAddress, 0, MemoryLayout<sockaddr_in>.size)
bind(sock, &sockAddress, UInt32(MemoryLayout<sockaddr_in>.size))


The
bind
line fails to compile with: cannot convert value of type 'sockaddr_in' to expected argument type 'sockaddr'

How do I cast the pointer?

Answer

You can write something like this:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
    sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1) {sockaddrPtr in
        bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.size))
    }
}

Or someone suggests this may be better:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
    let sockaddrPtr = UnsafeRawPointer(sockaddrInPtr).assumingMemoryBound(to: sockaddr.self)
    bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.size))
}

This article may be some help.

Comments