Archived

This topic is now archived and is closed to further replies.

Prozak

Structs-> Arrays-> Structs

Recommended Posts

This is somewhat of a long one, but i deem it simple to those that are more experienced in these ways... Having a struct, whose size (in bytes) might change over time, knowing its present size, wanting to send it through a socket connection, using an array of chars (which will always be greater than the maximum size of the struct), how do we get the insides of the structure into an array of chars? Then, when the receiving end gets it, how do they convert it from chars, back into the structure? I believe this involves copying memory, knowing the size of structures. Thanx for all the help, this one is getting me down, thanx,

[Hugo Ferreira][Positronic Dreams][]

Share this post


Link to post
Share on other sites
Well to do both ways its actually more complex

for one reason some systems are big endian and others are little endian.

To Get it into the characters

//you''d first want to label the size

memmove(charArray,&size,sizeof(size));

//then copy the structure data

memove(&charArray[sizeof(size)],&structData,size);

// end

now the problem is on the other side you might not have the same endian so you will also have to do an endian check and force either big or small endian on both sides...

Share this post


Link to post
Share on other sites
I struggled with this for a little while too.

The problem is that you have, like I did, equivicated two things which are in fact not the same. The structure that is used on the sending and receiving ends IS NOT the same construct that is used to transmit the data.

Now, if the data structures you want to send are very simple (meaning they contain no pointers - e.g. no variable length strings) you can just stomp them flat, send them over-the-wire, and pluck them back out. It depends on the networking API you''re using on how exactly you do this - with many you can just say ->Send((void*)&MyDataStruct, sizeof(MyDataStruct));

But that''s probably _not what you want to do. You want to make structures that describe the data, and then make methods that read/write the data out-of/into of a stream (a stream is more-or-less a buffer of bytes)

You want to take a structure like this:
  
struct BasePacket
{
WORD wPacketType;
};

struct ChatPacket : BasePacket
{
enum {ChatPacketType = 0x0001}
char* szChat;
WORD wLength;

ChatPacket()
{
wPacketType = ChatPacketType;
szChat = 0;
}

Write(BYTE* pStream, DWORD* dwBytesWritten)
{
*(WORD*)pStream = wPacketType; pStream+=2; //2 bytes in a word

wLength = strlen(szChat);
*(WORD*)pStream = wLength; pStream+=2;
memcpy(pStream, szChat, wLength); //pStream+=wLength needed only if we write more stuff

}

Read(BYTE* pStream)
{
wPacketType = *(WORD*)pStream; pStream+=2;
_ASSERT(wPacketType==ChatPacketType);
wLength = *(WORD*)pStream; pStream+=2;

szChat = new char[wLength];
memcpy(szChat, (char*)pStream, wLength);
}

};


Does that help?

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO

Share this post


Link to post
Share on other sites
I am not sure how the size of the struct will change.. unless what you mean is that inside the struct you will have pointers to heap-allocated memory. Even then, the size of the actual struct does not change (i.e. sizeof(MYSTRUCT) is determined at compile time). Be careful in the case where your struct contains pointers because what you will actually send is the VALUE of the pointer (a memory address) - which WILL NOT be valid on the other side.

Anyway, to copy a struct into a byte array just do a memcpy (not sure of syntax - operands may be reversed)

memcpy((void*)MYSTRUCTPTR, (void*)char_buffer, sizeof(MYSTRUCT));

or you may even be able to get away with casting...
char *buf = (char *)&MYSTRUCT
and get the size using sizeof(MYSTRUCT)


if your struct contains pointers to other data structures, which vary in size, then you need to break down all those data structures into the smallest possible units and send em (you can pack them together into sets to be more efficient). Then you have to rebuild the data structure heirarchy on the other side.


hope this helps,

BrianH


Share this post


Link to post
Share on other sites
quote:
Original post by pentium3id
a struct than contains:
int n;
char * string;

due to that string being there, doesn''t the size
become unpredictable, on part of the string being
capable of aquiring any length?


Nope, the size of that structure is always sizeof (int) + sizeof (char *), and sizeof (char *) does not change no matter how long your string is. Remember, a pointer is a pointer--it points to something. It''s always the same size. What it points to can change size, but the size of a pointer is fixed (4 bytes on most PC-based platforms).

Like Magmai Kai Holmlor said, it''s only easy to do if it''s a flat structure, meaning there are no pointers. Since there is a pointer, it''s a non-flat structure (what would you call that, "bubbly structure?") you have a harder job.

Share this post


Link to post
Share on other sites
The heart of this matter was that I was having
problems understandin the (char *) issue, of course
it is a pointer, therefore only 4 bytes in length.

Concerning flat structures, can it be done, can
we move their innard contents into an array,
then from the array to another structure?

Thanx for tha help, you guys are great,

[Hugo Ferreira][Positronic Dreams][]

Share this post


Link to post
Share on other sites