I am implementing a network packet in golang. It was already implemented in C++. The purpose is to make the golang implemented client communicate with C++ implemented server.
They will communicate by packet. The packet struct is:
type Packet struct {
length uint32
nameLen uint8
data []byte
} // in golang
struct Packet {
uint32_t length;
uint8_t nameLen;
byte data[];
} // in C++
Their underlined structure is byte array. When receiving a message in byte array format. We need to translate it into Packet.
auto p = reinterpret_cast<Packet*>(buffer); // in c++
(buffer's alignment is manually set as 64)
p := (Packet)(unsafe.Pointer(&buffer)) // in golang
To make them communicate, their struct alignment should keep the same.
Here comes the question: After printing out their alignment, I get this:
type Packet struct {
length uint32 // alignment 8
nameLen uint8 // alignment 8
data []byte // alignment 8
}
struct Packet {
uint32_t length; // alignment 4
uint8 nameLen; // alignment 4
data []byte; // alignment 1
}
They will decode the message differently due to the alignment is different.
I can not change the C++ code.
Q1: Is there any way to set struct fields alignment in golang?
Q2: Is there a better way to implement golang Packet to avoid alignment mismatch when casting buffer into packet?
According to Adrian and Volker's comment,
Q1: No
Q2: Do some programming to unpack fields individually.
In encoding/binary package, we have
func PutUVarint
It encodes a uint64 into buf and returns the number of bytes written. Somehow this package dont have public function to encode uint32. So I did something similar:
func PutUint32(b []byte, v uint32) {
_ = b[3] // early check
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
} // assume it's littleEndian
// to store packet length into buffer.
PutUint32(buffer, pkt.length)