protobuf lib库的使用
发布日期:2021-08-12 02:36:37 浏览次数:5 分类:技术文章

本文共 7485 字,大约阅读时间需要 24 分钟。

问题记录:

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

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行,并且别名应该留空!

 

2、jsoncpp的下载和使用

  jsoncpp源码可以从github上得到:

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

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

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

 

3、遍历proto文件中的所有消息以及所有字段

1 #include 
2 #include
3 #include
4 #include
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 }

 

转载于:https://www.cnblogs.com/rmthy/p/8475922.html

转载地址:https://blog.csdn.net/weixin_30642561/article/details/97324845 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Bootstrap 按钮颜色
下一篇:如何学习vc++

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月16日 09时19分29秒