文章目錄
protocol buffer虽然很好用,但是每次修改proto文件之后就需要重新编译生成消息代码,然后再相应的修改应用程序,用久了就有了繁琐的感觉,还好protocol buffer也提供了动态解析的功能,虽然效率低了点,但也是可以接受的(用protocol buffer3.0测试大概慢了5倍左右)。
proto文件如下,my.proto
1 2 3 4 5 6
| syntax = "proto3"; message mymsg { uint32 len = 1; uint32 typ = 2; }
|
动态编码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream> #include <string> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/dynamic_message.h> #include <google/protobuf/compiler/importer.h> using namespace std; using namespace google::protobuf; using namespace google::protobuf::compiler; int main() { DiskSourceTree sourceTree; sourceTree.MapPath("", "./"); Importer importer(&sourceTree, NULL); importer.Import("my.proto"); const Descriptor *descriptor = importer.pool()->FindMessageTypeByName("mymsg"); cout << descriptor->DebugString(); DynamicMessageFactory factory; const Message *message = factory.GetPrototype(descriptor); const FieldDescriptor *field = NULL; field = descriptor->FindFieldByName("len"); const FieldDescriptor *field1 = NULL; field1 = descriptor->FindFieldByName("typ"); Message *msg = message->New(); const Reflection *reflection = msg->GetReflection(); reflection->SetUInt32(msg, field, 1); reflection->SetUInt32(msg, field1, 2); std::string sout; msg.SerializeToString(&sout); delete msg; return 0; }
|
动态解析
1 2 3 4 5 6 7 8 9
| Message *msg = message->New(); msg->ParseFromString(sout); const Reflection *reflection = msg->GetReflection(); const FieldDescriptor *field = NULL; field = descriptor->FindFieldByName("len"); reflection->GetUInt32(*msg, field); field = descriptor->FindFieldByName("typ"); reflection->GetUInt32(*msg, field); delete msg;
|
其中message的获取方式和上面编码的代码一样。
动态生成消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| FileDescriptorProto file_proto; file_proto.set_name("my.proto"); file_proto.set_syntax("proto3"); DescriptorProto *message_proto = file_proto.add_message_type(); message_proto->set_name("mymsg"); FieldDescriptorProto *field_proto = NULL; field_proto = message_proto->add_field(); field_proto->set_name("len"); field_proto->set_type(FieldDescriptorProto::TYPE_UINT32); field_proto->set_number(1); field_proto->set_label(FieldDescriptorProto::LABEL_OPTIONAL); field_proto = message_proto->add_field(); field_proto->set_name("typ"); field_proto->set_type(FieldDescriptorProto::TYPE_UINT32); field_proto->set_number(2); DescriptorPool pool; const FileDescriptor *file_descriptor = pool.BuildFile(file_proto); cout << file_descriptor->DebugString();
|
上面代码所生成的结构和最开始的my.proto文件是一样的。
通过这三种方式就可以动态生成动态解析所有的内容了。
本文参考内容http://www.searchtb.com/2012/09/protocol-buffers.html