Deep-copying with ProtoBuf in C/C++

Roney Michael picture Roney Michael · Apr 27, 2015 · Viewed 7.6k times · Source

Say I had an array of pointers, each of which points to structs which may once again have pointers to other structs in them; is it possible to handle serializing this using protobuf? If so, how?

Any help would be greatly appreciated.

Answer

huu picture huu · Apr 28, 2015

The way you're thinking about this problem is the reverse of how you need to think if you're considering protobufs. Protobufs don't take an existing data structure and serialize them. They take a serialization protocol and create data structures for you that you populate.

With that said, nested serialization is pretty simple:

// nested.proto
message Inner {
    required string value = 1;
}

message Outer {
    required Inner inner = 1;
}

message Pointers {
    repeated Outer outer = 1;
}

Assuming you've correctly compiled this, you can use this protocol working from the outside in. That is, you start with the highest structure, Pointers, and work your way into the Inner object:

Pointers pointers;
for (int i = 0; i < 10; ++i) {
    auto outer = pointers.add_outer();
    auto inner = outer->mutable_inner();
    inner->set_value(std::to_string(i));
}

std::stringstream stream;
pointers.SerializeToOstream(&stream);

...

Pointers parsed_pointers;
parsed_pointers.ParseFromIstream(&stream);
for (int i = 0; i < parsed_pointers.outer_size(); ++i) {
    std::cout << parsed_pointers.outer(i).inner().value() << std::endl;
}

// This prints 0, 1, 2, ..., 9 all on their own lines

It's possible to start with the Inner message, but the way you pass ownership to an Outer message is not as simple or obvious:

Inner* inner = new Inner();
inner->set_value("Hello world");
Outer outer;
outer.set_allocated_inner(inner);

Calling that method will capture ownership of the inner pointer so that you shouldn't manually delete it yourself.