Reputation: 2416
I'm a C# developer, writing a client for a server written in C++. The server streams some arbitrary data over TCP/IP to the client, and we have to reassemble it on the other end. The server sends us first a description of the data, then the data itself.
Problematic Structure:
struct Inner_S
{
double a;
double b[4][4];
};
#pragma pack(1)
struct Packed_S
{
uint8_t c;
Inner_S d;
};
The server is telling the client that the outer structure has an alignment of 1, and the inner structure has an alignment of 8. The protocol spec says:
Alignment of fields within a streamed structure is done according to the Itanium 64-bit C++ Application Binary Interface specification (i.e. the same as a typical GNU compiler on a typical 64-bit platform).
I found the Itanium 64-bit C++ Application Binary Interface specification. I think the part I am looking for is in "Allocation of Members Other Than Virtual Bases" but I get lost in there.
On the C# side I'm reading the data stream and packing my own class with the values extracted from the structure. I need to know where exactly in the stream to look for each element of the structure.
I'm currently handling the structure this way which is wrong according to my users:
(begin structure with alignment 1)(no padding needed)(read simple value)c(begin inner structure with alignment 8)(add padding to alignment 8)0000000(read field)aaaaaaaa(begin array)(read simple value)bbbbbbbb.....
That method is supported by at least one site.
So, when I'm parsing this data, how do I handle alignment in Inner_S
?
caaaaaaaabbbbbbbb.... (I think?) caaaaaaaa0000000bbbbbbbb.... (looks wrong)
Upvotes: 5
Views: 1315
Reputation: 3022
As suggested by @Cameron I tried this with offsetof
since this involves POD types.
#include <iostream>
#include <cstddef>
#include <cstdint>
using namespace std;
struct Inner_S
{
double a;
double b[4][4];
};
#pragma pack(1)
struct Packed_S
{
uint8_t c;
Inner_S d;
};
int main() {
cout << "Size: " << sizeof(Packed_S) << endl;
cout << "c offset: " << offsetof(Packed_S, c) << endl;
cout << "d offset: " << offsetof(Packed_S, d) << endl;
cout << "a offset: " << offsetof(Packed_S, d.a) << endl;
cout << "b offset: " << offsetof(Packed_S, d.b) << endl;
return 0;
}
Output
Size: 137
c offset: 0
d offset: 1
a offset: 1
b offset: 9
So using your notation the structure is packed as caaaaaaaabbbbbbbb....
. Note that if you take out the #pragma pack(1)
directive the compiler adds 3 bytes of padding after c
.
Upvotes: 6