protobuf в C ++ с динамическим связыванием для google :: protobuf :: Message - PullRequest
0 голосов
/ 21 октября 2019

Работая с protobuf в C ++, у меня есть серия сообщений, которые будут совместно использовать одну пару пользовательских API кодирования и декодирования, например, Pack () и Unpack ();

Но вскоре я понимаю, что ядолжен жестко закодировать типы сообщений, чтобы иметь возможность декодировать данные в правильную структуру данных из потока.

Поскольку наследование не поддерживается, я затем посмотрел на средство Any. Тем не менее, официальный документ слишком краткий, чтобы привести меня с рабочим примером.

Я хотел бы подтвердить, работает ли Any следующим образом:

Скажите, если у меня есть несколько сообщенийтипы, которые мне нужно создать из фабрики на стороне декодера, затем ...

Шаг # 1: я должен определить свой proto3 следующим образом

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;
}

Шаг 2: Кодер будетработать так:

//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);

Шаг № 3: Наконец, декодеру потребуется

// 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);
}

Работает ли он таким образом?

1 Ответ

0 голосов
/ 07 ноября 2019

Поскольку никто не может ответить, я сообщаю о своих собственных выводах.

Нам не нужен явный идентификатор в протоколе. Any имеет встроенный идентификатор, сгенерированный Protobuf автоматически.

При декодировании просто вызовите назначенный метод, чтобы получить идентификатор из объекта Any, и мы можем сопоставить его с любыми пользовательскими шаблонами.

myAnyMsg.type_url()

Типичный URL выглядит следующим образом

type.googleapis.com/<message_type_defined_in_proto>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...