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 }
相關文章
相關標籤/搜索