protobuf lib库的使用

问题记录:python

一、在使用protobuf反射机制动态加载解析proto文件时,发现当proto文件中含有import系统proto文件的语句时,没法解析文件,解决方法是添加路径映射。ios

1 google::protobuf::compiler::DiskSourceTree sourceTree; 2 sourceTree.MapPath("data", "./data"); 3 sourceTree.MapPath("", "D:\\Documents\\Program\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include"); 4 google::protobuf::compiler::Importer importer(&sourceTree, NULL); 5 const google::protobuf::FileDescriptor *fileDescriptor = importer.Import("data/test.proto");

  代码如上,其中的第3行为解决方案,增长以后才能正确解析。分析其缘由是,Importer对象用于导入并解析proto文件,当proto文件中import了其余proto文件时,Importer对象递归导入并解析该proto文件;第二行告诉了Importer去哪里找test.proto,可是却没有告诉Importer去哪里找系统自带的proto文件,所以须要加上第3行,而且别名应该留空!git

 

二、jsoncpp的下载和使用github

  jsoncpp源码能够从github上获得:jsoncpp-master.zipjson

  解压后使用python执行根目录下的 amalgamate.py ,这个脚本将jsoncpp的头文件和源代码进行了合并,最终合并成了三个文件:oop

  dist\json\json.h  dist\json\json-forwards.h  dist\jsoncpp.cppgoogle

  使用时把 jsoncpp.cpp文件连同json文件夹一块儿拷贝到工程目录下,二者保持同级,代码中包含 json\json.h 便可。spa

 

三、遍历proto文件中的全部消息以及全部字段debug

 1 #include <iostream>
 2 #include <google/protobuf/compiler/importer.h>
 3 #include <google/protobuf/dynamic_message.h>
 4 #include <google/protobuf/util/json_util.h>
 5 
 6 int parseProtoFile()  7 {  8     // 准备配置好文件系统
 9  google::protobuf::compiler::DiskSourceTree sourceTree;  10     // 将当前路径映射为项目根目录 , project_root 仅仅是个名字,你能够你想要的合法名字.
 11     sourceTree.MapPath("data", "./data");  12     sourceTree.MapPath("", "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include");  13     // 配置动态编译器.
 14     google::protobuf::compiler::Importer importer(&sourceTree, NULL);  15     // 动态编译proto源文件。 源文件在./source/proto/test.proto .
 16     auto fileDescriptor = importer.Import("data/complex.proto");  17 
 18 
 19     std::cout << fileDescriptor->message_type_count() << std::endl;  20     for (auto i = 0; i < fileDescriptor->message_type_count(); i++)  21  {  22         auto descriptor = fileDescriptor->message_type(i);  23         
 24         std::cout << descriptor->name() << " " << descriptor->field_count() << " " << descriptor->nested_type_count() << std::endl;  25 
 26         auto descriptor1 = descriptor->containing_type();  27 
 28         if (descriptor1)  29  {  30             std::cout << descriptor1->name() << std::endl;  31  }  32  }  33     
 34     std::cout << fileDescriptor->name() << std::endl;  35     
 36 
 37     auto descriptor = fileDescriptor->message_type(1);  38     for (auto i = 0; i < descriptor->field_count(); i++)  39  {  40         auto fieldDes = descriptor->field(i);  41  google::protobuf::SourceLocation outLocation;  42         if (fieldDes->GetSourceLocation(&outLocation))  43  {  44             printf("%s: %d %d %d %d\nleading_comments:%s\ntrailing_comments:%s\n",  45                 fieldDes->full_name().c_str(),  46  outLocation.start_line, outLocation.start_column, outLocation.end_line, outLocation.end_column,  47  outLocation.leading_comments.c_str(), outLocation.trailing_comments.c_str());  48             for (auto comment : outLocation.leading_detached_comments)  49  {  50                 printf("leading_detached_comments:%s\n", comment.c_str());  51  }  52  }  53         else
 54  {  55             std::cout << "fail" << std::endl;  56  }  57  }  58     
 59 #if 0
 60     // 如今能够从编译器中提取类型的描述信息.
 61     auto descriptor1 = importer.pool()->FindMessageTypeByName("T.Test.InMsg");  62     
 63     // 建立一个动态的消息工厂.
 64  google::protobuf::DynamicMessageFactory factory;  65     // 从消息工厂中建立出一个类型原型.
 66     auto proto1 = factory.GetPrototype(descriptor1);  67     // 构造一个可用的消息.
 68     auto message1 = proto1->New();  69     // 下面是经过反射接口给字段赋值.
 70     auto reflection1 = message1->GetReflection();  71     auto filed1 = descriptor1->FindFieldByName("id");  72     reflection1->SetUInt32(message1, filed1, 1);  73 
 74     // 打印看看
 75     std::cout << message1->DebugString() << std::endl;  76 
 77     std::string output;  78     google::protobuf::util::MessageToJsonString(*message1, &output);  79     std::cout << output << std::endl;  80 
 81     // 删除消息.
 82     delete message1;  83 #endif
 84     return 0;  85 }  86 
 87 #define Log(format, ...) printf(format, __VA_ARGS__)
 88 
 89 void printOneField(const google::protobuf::FieldDescriptor *fieldDescriptor)  90 {  91     Log(" field[%d]: name %s, full name %s, json name %s, type %s, cpp type %s\n",  92         fieldDescriptor->index(), fieldDescriptor->name().c_str(), fieldDescriptor->full_name().c_str(), fieldDescriptor->json_name().c_str(),  93         fieldDescriptor->type_name(), fieldDescriptor->cpp_type_name());  94     Log(" debug string:%s\n", fieldDescriptor->DebugString().c_str());  95 }  96 
 97 void printOneMessage(const google::protobuf::Descriptor *descriptor)  98 {  99     // 消息的整体信息
100     Log("msg[%d]: name %s, full name %s, field count %d, nested type count %d\n", 101         descriptor->index(), descriptor->name().c_str(), descriptor->full_name().c_str(), descriptor->field_count(), 102         descriptor->nested_type_count()); 103     Log("\tdebug string: %s\n", descriptor->DebugString().c_str()); 104 
105     // 遍历消息的全部字段
106     for (int fieldLoop = 0; fieldLoop < descriptor->field_count(); fieldLoop++) 107  { 108         const google::protobuf::FieldDescriptor *fieldDescriptor = descriptor->field(fieldLoop); 109 
110  printOneField(fieldDescriptor); 111  } 112 
113     // 遍历消息的全部嵌套消息
114     for (int nestedLoop = 0; nestedLoop < descriptor->nested_type_count(); nestedLoop++) 115  { 116         const google::protobuf::Descriptor *nestedDescriptor = descriptor->nested_type(nestedLoop); 117 
118  printOneMessage(nestedDescriptor); 119  } 120 } 121 
122 void printOneFile(const google::protobuf::FileDescriptor *fileDescriptor) 123 { 124     Log("******** message info in proto file, msg count %d ********\n", fileDescriptor->message_type_count()); 125 
126     // 遍历文件中的全部顶层消息
127     for (int msgLoop = 0; msgLoop < fileDescriptor->message_type_count(); msgLoop++) 128  { 129         const google::protobuf::Descriptor *descriptor = fileDescriptor->message_type(msgLoop); 130 
131  printOneMessage(descriptor); 132  } 133 } 134 
135 bool testProto(const char *protoIncludePath, const char *testProtoPath, const char *testProtoFile) 136 { 137     // 配置文件系统
138  google::protobuf::compiler::DiskSourceTree sourceTree; 139     sourceTree.MapPath("", protoIncludePath); 140     sourceTree.MapPath("data", testProtoPath); 141     //sourceTree.MapPath("data", "./data"); 142     //sourceTree.MapPath("", "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include"); 143     // 配置动态编译器
144     google::protobuf::compiler::Importer importer(&sourceTree, NULL); 145     // 动态编译proto源文件
146     const google::protobuf::FileDescriptor *fileDescriptor = importer.Import("data/" + std::string(testProtoFile)); 147 
148     if (fileDescriptor == NULL) 149  { 150         printf("import \"%s\" failed, last error msg: %s\n", testProtoFile, sourceTree.GetLastErrorMessage().c_str()); 151         return false; 152  } 153 
154  printOneFile(fileDescriptor); 155 
156     return true; 157 } 158 
159 int main() 160 { 161     const char *protoIncludePath = "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include"; 162     const char *testProtoPath = "C:\\Users\\Administrator\\Desktop\\Document\\C++\\protobufTest\\protobufTest\\data"; 163     const char *testProtoFile = "complex.proto"; 164 
165  testProto(protoIncludePath, testProtoPath, testProtoFile); 166 
167     //parseProtoFile(); 168     //printf("Hello world!\n");
169     return 0; 170 }
相关文章
相关标签/搜索