[swift-users] Canonical way to cast C structs

Bouke Haarsma bouke at haarsma.eu
Mon Sep 12 14:25:51 CDT 2016


Hi all,

Inside my CFSocketCallBack a pointer to a sockaddr is provided wrapped in a CFData structure. The sockaddr could be either a sockaddr_in (IPv4) or sockaddr_in6 (IPv6) struct. In order to discover which struct you’re dealing with, the attribute sa_family can be inspected. In C this would look something like this:

struct sockaddr_storage sa;

switch (((sockaddr*)&sa)->sa_family)
{
    case AF_INET:
        inet_ntop(AF_INET, &(((sockaddr_in*)&sa)->sin_addr), ...);
        break;
    case AF_INET6:
        inet_ntop(AF_INET6, &(((sockaddr_in6*)&sa)->sin6_addr), ...);
        break;
}
(from: http://stackoverflow.com/a/13167913)

Wheras to do this in Swift 3, the only way I found thus far is this:

var generic = CFDataGetBytePtr(data).withMemoryRebound(to: sockaddr.self, capacity: 1) {
    return $0.pointee
}
switch generic.sa_family {
case sa_family_t(AF_INET):
    let ipv4 = withUnsafePointer(to: &generic) {
        $0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
            $0.pointee
        }
    }
    //...
case sa_family_t(AF_INET6):
    let ipv6 = withUnsafePointer(to: &generic) {
        $0.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) {
            $0.pointee
        }
    }
    //...
default:
    //…
}

This looks very ugly with all the closures and ``withMemoryRebound``. Is there a better way to do this? I think there should be something more “Swifty”.

—
Bouke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160912/8c6313ff/attachment.html>


More information about the swift-users mailing list