Hi Martin, > On 28 Apr 2017, at 12:59, Martin R <martinr...@gmail.com> wrote: > > As far as I know, the only guarantee is made for structures imported from C. > From > https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160516/001968.html > : > > Swift structs have unspecified layout. If you depend on a specific layout, > you should define the struct in C and import it into Swift for now.
Thanks! Yes I know structs have unspecified layout but that doesn't necessarily mean tuples have that too. Especially if you consider that C structs having fixed sized arrays in them get imported as tuples. See for example this: typedef struct __siginfo { int si_signo; /* signal number */ int si_errno; /* errno association */ int si_code; /* signal code */ pid_t si_pid; /* sending process */ uid_t si_uid; /* sender's ruid */ int si_status; /* exit value */ void *si_addr; /* faulting instruction */ union sigval si_value; /* signal value */ long si_band; /* band event for SIGPOLL */ unsigned long __pad[7]; /* Reserved for Future Use */ } siginfo_t; gets imported as --- SNIP --- public struct __siginfo { public var si_signo: Int32 /* signal number */ public var si_errno: Int32 /* errno association */ public var si_code: Int32 /* signal code */ public var si_pid: pid_t /* sending process */ public var si_uid: uid_t /* sender's ruid */ public var si_status: Int32 /* exit value */ public var si_addr: UnsafeMutableRawPointer! /* faulting instruction */ public var si_value: sigval /* signal value */ public var si_band: Int /* band event for SIGPOLL */ public var __pad: (UInt, UInt, UInt, UInt, UInt, UInt, UInt) /* Reserved for Future Use */ public init() public init(si_signo: Int32, si_errno: Int32, si_code: Int32, si_pid: pid_t, si_uid: uid_t, si_status: Int32, si_addr: UnsafeMutableRawPointer!, si_value: sigval, si_band: Int, __pad: (UInt, UInt, UInt, UInt, UInt, UInt, UInt)) } public typealias siginfo_t = __siginfo --- SNAP --- So the `unsigned long __pad[7]` becomes `public var __pad: (UInt, UInt, UInt, UInt, UInt, UInt, UInt)` and given that, this should really be legal, right? var random_uint_7_tuple: (UInt, UInt, UInt, UInt, UInt, UInt, UInt) = (1, 2, 3, 4, 5, 6, 7) var si = siginfo_t() _ = withUnsafeMutablePointer(to: &si.__pad) { (si_pad_ptr) -> Void in return withUnsafeMutablePointer(to: &random_uint_7_tuple) { (tuple_ptr) -> Void in si_pad_ptr.assign(from: tuple_ptr, count: 1) } } from this example I believe we can see that the Swift values of type `(UInt, UInt, UInt, UInt, UInt, UInt, UInt)` MUST have the same layout as `unsigned long[7]` imported from C, right? withUnsafeMutablePointer() to those values gives me a UnsafeMutablePointer<(UInt, UInt, UInt, UInt, UInt, UInt, UInt)> in both cases. That's why I think inducing unspecified tuple layout from unspecified struct layout doesn't work. Structs are nominal types (so I can't recreate the same type that was imported from C in pure Swift. Tuples on the other hand are structural types which means I am able to recreate the same type that is imported from C in Swift (which is what I did in the example above). Does that make sense? Cheers, Johannes > > and from > https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160516/001980.html > : > > That's not necessary. You can leave the struct defined in C and import it > into Swift. Swift will respect C's layout. > > Regards, Martin > > >> On 28. Apr 2017, at 13:03, Johannes Weiss via swift-users >> <swift-us...@swift.org> wrote: >> >> Hi swift-users, >> >> (sorry for the cross post to swift-dev, but wasn't sure where it belongs) >> >> I tried to find guarantees about the memory layout Swift tuples but couldn't >> find anything. The reason I ask is because I'd like to use them as fixed >> sized (stack allocated) arrays. I'm pretty sure they're actually not >> guaranteed to be stack allocated but highly likely I assume :). >> >> Am I correct in assuming that >> >> let swift_events: (kevent, kevent) = ... >> >> has the same memory layout as >> >> struct kevent c_events[2] = ... >> >> ? In other words, is this legal: >> >> var events = (kevent(), kevent()) >> withUnsafeMutableBytes(of: &events) { event_ptr in >> precondition(MemoryLayout<kevent>.size * 2 == event_ptr.count) >> if let ptr = event_ptr.baseAddress?.bindMemory(to: kevent.self, >> capacity: 2) { >> return kevent(someFileDescriptor, ptr, 2, ptr, 2, nil) >> } >> } >> >> I'm assuming yes but I'd like to make sure. >> >> Many thanks, >> Johannes >> >> _______________________________________________ >> swift-users mailing list >> swift-us...@swift.org >> https://lists.swift.org/mailman/listinfo/swift-users > _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev