How to dereference multiple void pointers in structs into 1 piece of memory?

655 views Asked by At

I am working on a project where I need to send over a certain IPC stack, (in my case, LCM), and the thing is I need to provide the IPC a variable length struct. I have

struct pack1 {int value1; int value2;};
struct pack2 {void *data; int data_size;}; 
//data won't always point to pack1 types

I have a pointer to pack2, and I need something like serialization, so I can send this pack2 over the network to another process.

Anyone knows how?

4

There are 4 answers

1
payne On BEST ANSWER

LCM supports variable length arrays, see the "Arrays" section in the reference manual: http://lcm.googlecode.com/svn-history/r401/www/reference/lcm/tutorial-lcm-language.html

However, your data is accessed via void*, which is just a pointer to an "unknown" type. If your data is just bytes, then it might work to treat it as a byte array, like this in your LCM definition:

struct pack2 {
  int32_t data_size;
  unsigned char data[data_size};
}
0
Lundin On

Please keep in mind that a struct may contain any number of padding bytes. This is especially troublesome when writing any form of data protocol. If using sizeof() on it, you must be sure that the compiler has padding disabled. The portable way is to go through the struct member by member and send them.

4
par On

You can do it like this:

struct pack2        *p;

p = (struct pack2 *) malloc( sizeof(struct pack2) + 1024 );
p->data_size = 1024;
p->data = (char *) p + sizeof(struct pack2);

The only caveat is that you have to make sure the target platform maintains the endianness of the original platform in data_size and you have to be sure struct pack2 is the same size on both platforms.

1
zwol On

Any time you serialize a data structure containing pointers, you need to convert those pointers into something other than pointers. One possibility is to turn them into offsets within the data stream; another possibility is to remove them altogether and rely on the organization of the stream itself. Either way, you need to write down the serialization format with great precision; the rule of thumb is, someone should be able to write code from scratch that either produces or consumes the serialization without any information other than the specification you write.

Here's one possible way to serialize the data structures you showed:

# Each row is a 32-bit unsigned value in network byte order.
| number of pairs following     |
| [0].value1                    |
| [0].value2                    |
| [1].value1                    |
| [2].value2                    |
  ...
| [N].value1                    |
| [N].value2                    |

Good examples - both of how to do this sort of thing and how to document it - may be found in the TCP and IP RFCs, or the PNG specification.