Igal
(Igal)
1
I need to use a struct to implement some network protocol.
I need to send the struct as a byte stream and when I receive a reply to convert it back to the struct.
Currently, I am using these encode and decode functions:
func encode( value: T) -> NSData {
return withUnsafePointer(to:value) { p in
NSData(bytes: p, length: MemoryLayout.size(ofValue:value))
}
}
func decode<T>(data: NSData) -> T {
let pointer = UnsafeMutablePointer<T>.allocate(capacity: MemoryLayout.size(ofValue:T.self))
data.getBytes(pointer)
return pointer.move()
}
The struct which I need to convert looks like this:
struct start_ctrl_conn {
var header:header;
var version:UInt16;
var reserved:UInt8;
var framing_cap:UInt32;
var bearer_cap:UInt32;
var max_channels:UInt16;
var firmware_rev:UInt16; */
var hostname = Array.init(repeating: UInt8(0), count: 64);
var vendor = Array.init(repeating: UInt8(0), count: 64);
};
struct header {
var length:UInt16
var pptp_type:UInt16
var magic:UInt32
var ctrl_type:UInt16
var reserved0:UInt16
}
This doesn't seem to work.
The memory layout size give 48 bytes no matter what, although there at least 156 bytes.
Is there a simple way to encode and decode to struct to byets an visa versa?,
what am I doing wrong?
Cheers
Tino
(Tino)
2
I guess the arrays are the problem; sadly, the usual workaround is a tuple with 64 elements...
Igal
(Igal)
3
Do you have a link or code snippet example how to implement this ?
Karl
(👑🦆)
4
Swift does not make any guarantees about the layout of objects; you should define your data-type in C and import it in to Swift (see any of the SwiftPM tutorials about C interop).
And yes, Swift Arrays are dynamically-resizable (analogous to std::vector), so they are actually wrapped pointers to (generally) heap-allocated storage.
1 Like
Igal
(Igal)
5
AlexanderM
(Alexander Momchilov)
6
I think you should use the Codable system, using a custom encoder/decoder that writes/reads byte to/from a Data. That way you can make your layout explicit, rather than piggy backing off of the unfixed layout that the compiler comes up for you.
Karl
(👑🦆)
7
Yes.
The easiest way to get a small C module building and all the correct paths sent to your Swift module is via SwiftPM. It will automatically detect a C library target, and your Swift module can depend on it and use the type defined there.