#include <sstream>#include "google/protobuf/message.h" int main(int argc, char **argv) { if( argc > 1) { // This will fail to compile, as Message is pure abstract google::protobuf::Message* message = NULL; //new google::protobuf::Message(); std::istringstream ss(std::string(argv[1],strlen(argv[1]))); message->ParseFromIstream(&ss); // do something with the message // ... } return 0; }
Basically I'm trying to work out how to deserialize a protobuf message without using the generated headers, as we're likely to get messages that weren't generated at compile time. I've looked through the documentation, but I only seem to be able to find ones that use generated classes to deserialize, or that use a Descriptor from a generated class to create a DynamicMessage, which I can't seem to work out how to do when we don't have the proto.
import "google/protobuf/descriptor.proto";
message MetaMessage {
required google.protobuf.FileDescriptorProto message_descriptor = 1;
required string message_typename = 2;
required bytes message_data = 3;
}void deserializeMessage( const char* filePath ) { std::ifstream filestr( filePath, std::ifstream::binary ); // Create MetaMessage object and parse from stream MetaMessage message; message.ParseFromIstream(&filestr); // First try and find the descriptor, incase it's a compiled in type const google::protobuf::Descriptor* descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName( message.message_typename() ); const google::protobuf::Message* prototype = NULL; // if we have a descriptor, then get the Prototype message if( descriptor ) { prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype( descriptor ); } else { // Otherwise, add the descriptor to my Descriptor Pool static google::protobuf::DescriptorPool myPool; myPool.BuildFile( message.message_descriptor() ); descriptor = myPool.FindMessageTypeByName( message.message_typename() ); // create a factory from descriptor pool, and get prototype static google::protobuf::DynamicMessageFactory myFactory(&myPool); prototype = myFactory.GetPrototype( descriptor ); } // now we have prototype, can create mutable type and deserialize if( prototype ) { google::protobuf::Message* payload = prototype->New(); assert( message.has_message_data() ); payload->ParseFromString( message.message_data() ); std::string msg = payload->GetReflection()->GetString(*payload, descriptor->FindFieldByName("message")); std::cout << msg << std::endl; } }
int main(int argc, char **argv) { if
( argc > 1 )
{
deserializeMessage( argv[1] );
}
return 0;
}