[swift-users] Canonical way to cast C structs
Bouke Haarsma
bouke at haarsma.eu
Mon Sep 12 14:39:20 CDT 2016
Sorry for all the pings, but it appears that the code below doesn’t work after all;
> fatal error: can't unsafeBitCast between types of different sizes
So the question remains on how to perform the casts using Swift?
—
Bouke
> On 12 sep. 2016, at 21:37, Bouke Haarsma <bouke at haarsma.eu> wrote:
>
>
> Sorry, missed the first line when copying:
>
> let generic = unsafeBitCast(CFDataGetBytePtr(data), to: sockaddr.self)
> switch generic.sa_family {
> case sa_family_t(AF_INET):
> let ipv4 = unsafeBitCast(generic, to: sockaddr_in.self)
> //...
> case sa_family_t(AF_INET6):
> let ipv6 = unsafeBitCast(generic, to: sockaddr_in6.self)
> //...
> default:
> //...
> }
>
> —
> Bouke
>
>> On 12 sep. 2016, at 21:35, Bouke Haarsma <bouke at haarsma.eu <mailto:bouke at haarsma.eu>> wrote:
>>
>> Ah the missing part of the puzzle appears to be unsafeBitCast(:to:), so the Swift version becomes this:
>>
>> switch generic.sa_family {
>> case sa_family_t(AF_INET):
>> let ipv4 = unsafeBitCast(generic, to: sockaddr_in.self)
>> //...
>> case sa_family_t(AF_INET6):
>> let ipv6 = unsafeBitCast(generic, to: sockaddr_in6.self)
>> //...
>> default:
>> //...
>> }
>>
>> —
>> Bouke
>>
>>> On 12 sep. 2016, at 21:25, Bouke Haarsma <bouke at haarsma.eu <mailto:bouke at haarsma.eu>> wrote:
>>>
>>> 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 <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/9bd3f391/attachment.html>
More information about the swift-users
mailing list