简体   繁体   中英

protobuf in C++ with dynamic binding for google::protobuf::Message

Working with protobuf in C++, I have a series of messages that will share a single pair of encoding and decoding custom API, eg, Pack() and Unpack();

But I soon realize that I must hardcode the message types to be able to decode the data into the correct data structure from stream.

Since inheritance is not supported, I then looked at the Any facility. However, the official doc is too concise to guide me with an working example.

I'd like to confirm whether or not the Any works like this:

Say if I have a few message types that I need to create from a factory on the decoder side, then...

Step #1: I must define my proto3 like this

syntax = "proto3";

import "google/protobuf/any.proto";

message Envelope {
   google.protobuf.Any actual_msg = 1;
   string id = 2;
}

message PublicProfile {
   string name = 1;
   int32 age = 2;
   bool isMale = 3;
}

message PrivateProfile {
   string nickname = 1;
   int32 money = 2;
}

Step 2: The encoder would work like this

//encoder.cpp

Envelope payload;
payload.set_id("my.com/msg/profile.public");
PublicProfile pp;
pp.name = "Tom";
pp.age = 30;
pp.isMale = true;
payload.get_actual_msg().PackFrom(pp); // NOT Sure how to use PackFrom at all!


int pakSize = payload.ByteSize()
std::string packet(pakSize, '\0');
google::protobuf::io::ArrayOutputStream aos((void*)packet.c_str(), pakSize);
google::protobuf::io::CodedOutputStream* cos = new google::protobuf::io::CodedOutputStream(&aos);
payload.SerializeToCodedStream(cos);

Step #3: Finally the decoder would need to

// decoder.cpp

Envelope payload;
google::protobuf::io::ArrayInputStream ais(packet.c_str(), packet.size());
google::protobuf::io::CodedInputStream cis(&ais);
payload->ParseFromCodedStream(&cis);
google::protobuf::Any actual_msg = payload.actual_msg();
if (payload.id() == "my.com/msg/profile.public") {
    PublicProfile pp;
    actual_msg.UnpackTo(&pp);
}

Does it work this way?

Since no one is up for an answer, I'm reporting my own findings.

We don't need an explicit ID in the protocol. Any has an ID built into it, generated by Protobuf automatically.

When decoding, simply call the designated method to retrieve the ID from the Any object and we are free to match it against any custom patterns

myAnyMsg.type_url()

A typical URL looks like this

type.googleapis.com/<message_type_defined_in_proto>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM