I'm trying to construct parser by the proto at runtime. I create dynamic message pointer by DynamicMessageFactory
, and I want to cast the pointer to the exact type so that I can get access to some fields directly (instead of by reflection).
Here is my code, the ShortDebugString()
output seems fine. But I didn't get the right value of field id
. Why?
#include "MyData.pb.h" // I use generated pb codes at the same time.
/*
file: MyData.proto
message MyData {
int32 id = 1;
};
*/
static const std::string message_type = "MyData";
std::ifstream proto_ifs("MyData.proto");
std::string proto_content((std::istreambuf_iterator<char>(proto_ifs)),
std::istreambuf_iterator<char>());
ArrayInputStream raw_input(proto_content.c_str(), proto_content.size());
Tokenizer input(&raw_input, NULL);
FileDescriptorProto file_desc_proto;
Parser parser;
if (!parser.Parse(&input, &file_desc_proto)) {
std::cerr << "Failed to parse .proto definition:" << proto_content;
return -1;
}
if (!file_desc_proto.has_name()) {
file_desc_proto.set_name(message_type);
}
google::protobuf::DescriptorPool pool;
const google::protobuf::FileDescriptor* file_desc = pool.BuildFile(file_desc_proto);
const auto* message_desc = file_desc->FindMessageTypeByName(message_type);
google::protobuf::DynamicMessageFactory factory;
factory.SetDelegateToGeneratedFactory(true);
const google::protobuf::Message* prototype_msg;
prototype_msg = factory.GetPrototype(message_desc);
google::protobuf::Message* mutable_msg = prototype_msg->New();
MyData tmp;
tmp.set_id(111);
int32_t msg_len;
const char* msg_data = tmp.SerializeToArray(msg_data, msg_len);
mutable_msg->ParseFromArray(msg_data, msg_len);
const MyData& my_data = static_cast<const MyData&>(*mutable_msg);
std::cout << mutable_msg->ShortDebugString() << "\n";
std::cout << my_data.ShortDebugString() << "\n";
std::cout << my_data.id() << "\n";
outputs:
id: 111
id: 111
0