M
ma740988
I'm faced with endian issues during communication across different
platforms.
So I've recommendations/tips (from one of these newsgroups - cant
recall which) on an approach (or two or three) that seems reasonable
and is based on issues that were encountered and how to handle them in
this situation.
One of which - the one I'm currently investigating - is as follows:
For discussion purposes consider atruct that'll be transmitted between
two plaforms (a and b). Platform a is little endian. b is big endian.
A sample struct is akin to.
//
typedef double tag_word;
struct t2_data
{
tag_word tag_word_;
bool lvt_enable : 1;
bool range : 1;
bool valid_mst : 1;
// more
};
struct t2_status
{
tag_word tag_word_;
bool lvt_status : 1;
bool range_status : 1;
bool msg_is_valid : 1;
unsigned int : 2;
unsigned int : 4;
// more
};
struct msg_header
{
unsigned int msg_size;
unsigned int msg_id;
unsigned int msg_count;
unsigned int msg_chksum;
};
// later
struct platform_a_to_b // little endian (platform a) to big endian
(platform b)
{
msg_header header;
t2_data t2_data_;
};
// later
struct platform_b_to_a // big endian (platform b) to little endian
(platform a)
{
msg_header header;
t2_status t2_stat;
};
The approach under investigation involves allocation of a buffer large
enough to hold the message being transmitted/received. So now: For
the receipt of message (IOW a receives from b or vice versa), I'll:
1. Allocate an unsigned char buffer large enough to hold the message.
2. Read the message into the buffer.
3. Convert the endianism of the data(if necessary).
4. Load each member of the model struct from the buffer.
Now I'm told that transmittal of messages is the reverse order of items
1 to 4, but that puzzles me. Why? With a 'few' tweaks heres the
reverse order as I see it:
1a. Allocate a unsinged char buffer large enough to hold the message.
This assumes a buffer hasn't already been allocated.
2a. Load each member of the model struct INTO (in this case lets take
the information from the struct and put into the buffer) the buffer.
3a. Convert the endianism of the data.
Item 2a seems flawed to me. The idea that I could just dump a struct
ino a byte buffer and send it across a wire seems like a bad idea, for
obvious reasons. Namely, I'm not guaranteed that the two plarforms
pack structs the same way and that would cause more headaches than it
will solve. That said, I'm puzzled about how this 'byte' buffer
approach works.
For those who've used this approach and have code that works, if its
possible to share (conversion code + sample struct) I'd appreaciate it.
Perusing _ACTUAL_ code assists me in 'getting my head around things'.
One other thing:
While it can be said that the requirements per the number of bytes for
a field is 'fixed' in a document, the types, - namely bool - specified
in the structs above need revisiting. I've been advised to follow
protocol below when dealing with structs and bit fields:
1. use only double, unsigned int (32 bits) and unsigned char.
2. if I need bool take and int, if I have to consider platforms using
different bool type sizes.
3. use double int and char (arrays) in that order.
4. make char arr's size a multiple of 4. (better multiple of 8).
I'll be re-visiting/investigating this approach.
platforms.
So I've recommendations/tips (from one of these newsgroups - cant
recall which) on an approach (or two or three) that seems reasonable
and is based on issues that were encountered and how to handle them in
this situation.
One of which - the one I'm currently investigating - is as follows:
For discussion purposes consider atruct that'll be transmitted between
two plaforms (a and b). Platform a is little endian. b is big endian.
A sample struct is akin to.
//
typedef double tag_word;
struct t2_data
{
tag_word tag_word_;
bool lvt_enable : 1;
bool range : 1;
bool valid_mst : 1;
// more
};
struct t2_status
{
tag_word tag_word_;
bool lvt_status : 1;
bool range_status : 1;
bool msg_is_valid : 1;
unsigned int : 2;
unsigned int : 4;
// more
};
struct msg_header
{
unsigned int msg_size;
unsigned int msg_id;
unsigned int msg_count;
unsigned int msg_chksum;
};
// later
struct platform_a_to_b // little endian (platform a) to big endian
(platform b)
{
msg_header header;
t2_data t2_data_;
};
// later
struct platform_b_to_a // big endian (platform b) to little endian
(platform a)
{
msg_header header;
t2_status t2_stat;
};
The approach under investigation involves allocation of a buffer large
enough to hold the message being transmitted/received. So now: For
the receipt of message (IOW a receives from b or vice versa), I'll:
1. Allocate an unsigned char buffer large enough to hold the message.
2. Read the message into the buffer.
3. Convert the endianism of the data(if necessary).
4. Load each member of the model struct from the buffer.
Now I'm told that transmittal of messages is the reverse order of items
1 to 4, but that puzzles me. Why? With a 'few' tweaks heres the
reverse order as I see it:
1a. Allocate a unsinged char buffer large enough to hold the message.
This assumes a buffer hasn't already been allocated.
2a. Load each member of the model struct INTO (in this case lets take
the information from the struct and put into the buffer) the buffer.
3a. Convert the endianism of the data.
Item 2a seems flawed to me. The idea that I could just dump a struct
ino a byte buffer and send it across a wire seems like a bad idea, for
obvious reasons. Namely, I'm not guaranteed that the two plarforms
pack structs the same way and that would cause more headaches than it
will solve. That said, I'm puzzled about how this 'byte' buffer
approach works.
For those who've used this approach and have code that works, if its
possible to share (conversion code + sample struct) I'd appreaciate it.
Perusing _ACTUAL_ code assists me in 'getting my head around things'.
One other thing:
While it can be said that the requirements per the number of bytes for
a field is 'fixed' in a document, the types, - namely bool - specified
in the structs above need revisiting. I've been advised to follow
protocol below when dealing with structs and bit fields:
1. use only double, unsigned int (32 bits) and unsigned char.
2. if I need bool take and int, if I have to consider platforms using
different bool type sizes.
3. use double int and char (arrays) in that order.
4. make char arr's size a multiple of 4. (better multiple of 8).
I'll be re-visiting/investigating this approach.