Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep-copying with ProtoBuf in C/C++

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.

like image 662
Roney Michael Avatar asked Apr 27 '15 21:04

Roney Michael


2 Answers

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.

like image 102
huu Avatar answered Oct 20 '22 19:10

huu


There is another method I think also helpful. Since .set_allocated_*(A) has a side effect which will destroy A. To just copy from A, you can try .mutable_*()->CopyFrom(A).

like image 42
Alanthink Avatar answered Oct 20 '22 21:10

Alanthink