0

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?

stacker
  • 68,052
  • 28
  • 140
  • 210
Sergio Campamá
  • 746
  • 1
  • 7
  • 14
  • I was able to do it, interfacing between each layer converting the struct into a char array... and then using the final char array and length in LCM. what bothers me now is that when dereferencing the void pointer into a struct that has floats, then the float gets messed up, but when using ints, it works fine.. – Sergio Campamá Feb 08 '11 at 17:30

4 Answers4

2

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};
}
payne
  • 13,833
  • 5
  • 42
  • 49
  • using this format, how can I represent (or convert) a struct as a byte array? and more importantly, how can I return that byte array into a struct? – Sergio Campamá Feb 08 '11 at 13:28
1

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.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 1
    Note: he's using LCM, which should handle all the marshalling. See: http://code.google.com/p/lcm/ – payne Feb 07 '11 at 20:15
0

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.

par
  • 17,361
  • 4
  • 65
  • 80
  • why the 1024 size? all the processes should run on the same machine, using the same source code... – Sergio Campamá Feb 08 '11 at 13:29
  • Just an example. You're going to record the actual size of the data in the data_size member. It can be as big as you need. I was demonstrating how to make a linear block of memory that contains the struct itself and the struct data. – par Feb 08 '11 at 20:23
  • shouldn't it be `+ 1024` instead of `* 1024`? – Sergio Campamá Feb 08 '11 at 21:01
  • Yes. Nice catch on the typo and fixed now. – par Feb 09 '11 at 05:52
0

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396