問題記錄: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 }