问题记录:

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

 google::protobuf::compiler::DiskSourceTree sourceTree;
sourceTree.MapPath("data", "./data");
sourceTree.MapPath("", "D:\\Documents\\Program\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include");
google::protobuf::compiler::Importer importer(&sourceTree, NULL);
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上得到:jsoncpp-master.zip

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

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

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

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

 #include <iostream>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/util/json_util.h> int parseProtoFile()
{
// 准备配置好文件系统
google::protobuf::compiler::DiskSourceTree sourceTree;
// 将当前路径映射为项目根目录 , project_root 仅仅是个名字,你可以你想要的合法名字.
sourceTree.MapPath("data", "./data");
sourceTree.MapPath("", "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include");
// 配置动态编译器.
google::protobuf::compiler::Importer importer(&sourceTree, NULL);
// 动态编译proto源文件。 源文件在./source/proto/test.proto .
auto fileDescriptor = importer.Import("data/complex.proto"); std::cout << fileDescriptor->message_type_count() << std::endl;
for (auto i = ; i < fileDescriptor->message_type_count(); i++)
{
auto descriptor = fileDescriptor->message_type(i); std::cout << descriptor->name() << " " << descriptor->field_count() << " " << descriptor->nested_type_count() << std::endl; auto descriptor1 = descriptor->containing_type(); if (descriptor1)
{
std::cout << descriptor1->name() << std::endl;
}
} std::cout << fileDescriptor->name() << std::endl; auto descriptor = fileDescriptor->message_type();
for (auto i = ; i < descriptor->field_count(); i++)
{
auto fieldDes = descriptor->field(i);
google::protobuf::SourceLocation outLocation;
if (fieldDes->GetSourceLocation(&outLocation))
{
printf("%s: %d %d %d %d\nleading_comments:%s\ntrailing_comments:%s\n",
fieldDes->full_name().c_str(),
outLocation.start_line, outLocation.start_column, outLocation.end_line, outLocation.end_column,
outLocation.leading_comments.c_str(), outLocation.trailing_comments.c_str());
for (auto comment : outLocation.leading_detached_comments)
{
printf("leading_detached_comments:%s\n", comment.c_str());
}
}
else
{
std::cout << "fail" << std::endl;
}
} #if 0
// 现在可以从编译器中提取类型的描述信息.
auto descriptor1 = importer.pool()->FindMessageTypeByName("T.Test.InMsg"); // 创建一个动态的消息工厂.
google::protobuf::DynamicMessageFactory factory;
// 从消息工厂中创建出一个类型原型.
auto proto1 = factory.GetPrototype(descriptor1);
// 构造一个可用的消息.
auto message1 = proto1->New();
// 下面是通过反射接口给字段赋值.
auto reflection1 = message1->GetReflection();
auto filed1 = descriptor1->FindFieldByName("id");
reflection1->SetUInt32(message1, filed1, ); // 打印看看
std::cout << message1->DebugString() << std::endl; std::string output;
google::protobuf::util::MessageToJsonString(*message1, &output);
std::cout << output << std::endl; // 删除消息.
delete message1;
#endif
return ;
} #define Log(format, ...) printf(format, __VA_ARGS__) void printOneField(const google::protobuf::FieldDescriptor *fieldDescriptor)
{
Log(" field[%d]: name %s, full name %s, json name %s, type %s, cpp type %s\n",
fieldDescriptor->index(), fieldDescriptor->name().c_str(), fieldDescriptor->full_name().c_str(), fieldDescriptor->json_name().c_str(),
fieldDescriptor->type_name(), fieldDescriptor->cpp_type_name());
Log(" debug string:%s\n", fieldDescriptor->DebugString().c_str());
} void printOneMessage(const google::protobuf::Descriptor *descriptor)
{
// 消息的总体信息
Log("msg[%d]: name %s, full name %s, field count %d, nested type count %d\n",
descriptor->index(), descriptor->name().c_str(), descriptor->full_name().c_str(), descriptor->field_count(),
descriptor->nested_type_count());
Log("\tdebug string: %s\n", descriptor->DebugString().c_str()); // 遍历消息的所有字段
for (int fieldLoop = ; fieldLoop < descriptor->field_count(); fieldLoop++)
{
const google::protobuf::FieldDescriptor *fieldDescriptor = descriptor->field(fieldLoop); printOneField(fieldDescriptor);
} // 遍历消息的所有嵌套消息
for (int nestedLoop = ; nestedLoop < descriptor->nested_type_count(); nestedLoop++)
{
const google::protobuf::Descriptor *nestedDescriptor = descriptor->nested_type(nestedLoop); printOneMessage(nestedDescriptor);
}
} void printOneFile(const google::protobuf::FileDescriptor *fileDescriptor)
{
Log("******** message info in proto file, msg count %d ********\n", fileDescriptor->message_type_count()); // 遍历文件中的所有顶层消息
for (int msgLoop = ; msgLoop < fileDescriptor->message_type_count(); msgLoop++)
{
const google::protobuf::Descriptor *descriptor = fileDescriptor->message_type(msgLoop); printOneMessage(descriptor);
}
} bool testProto(const char *protoIncludePath, const char *testProtoPath, const char *testProtoFile)
{
// 配置文件系统
google::protobuf::compiler::DiskSourceTree sourceTree;
sourceTree.MapPath("", protoIncludePath);
sourceTree.MapPath("data", testProtoPath);
//sourceTree.MapPath("data", "./data");
//sourceTree.MapPath("", "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include");
// 配置动态编译器
google::protobuf::compiler::Importer importer(&sourceTree, NULL);
// 动态编译proto源文件
const google::protobuf::FileDescriptor *fileDescriptor = importer.Import("data/" + std::string(testProtoFile)); if (fileDescriptor == NULL)
{
printf("import \"%s\" failed, last error msg: %s\n", testProtoFile, sourceTree.GetLastErrorMessage().c_str());
return false;
} printOneFile(fileDescriptor); return true;
} int main()
{
const char *protoIncludePath = "D:\\Documents\\Tools\\protobuf-3.0.2\\install\\x86\\debug\\include";
const char *testProtoPath = "C:\\Users\\Administrator\\Desktop\\Document\\C++\\protobufTest\\protobufTest\\data";
const char *testProtoFile = "complex.proto"; testProto(protoIncludePath, testProtoPath, testProtoFile); //parseProtoFile();
//printf("Hello world!\n");
return ;
}

protobuf lib库的使用的更多相关文章

  1. lib库dll库的使用方法与关系

    一.lib库 lib库有两种:一种是静态lib(static Lib),也就是最常见的lib库,在编译时直接将代码加入程序当中.静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是 ...

  2. 在VS中添加lib库的三种方法

    注意: 1.每种方法也要复制相应的DLL文件到相应目录,或者设定DLL目录的位置,具体方法为:"Properties" -> "Configuration Prop ...

  3. 如何把一个android工程作为另外一个android工程的lib库

    http://zhidao.baidu.com/question/626166873330652844 一个工程包含另一个工程.相当于一个jar包的引用.但又不是jar包反而像个package 在网上 ...

  4. Android so lib库远程http下载和动态注册

    一.背景 在开发Android应用程序的实现,有时候需要引入第三方so lib库,但第三方so库比较大,例如开源第三方播放组件ffmpeg库, 如果直接打包的apk包里面, 整个应用程序会大很多.经过 ...

  5. VS2010中添加lib库引用

    VS2010中添加lib库引用: 1 菜单  项目---> 属性--->配置属性-->链接器---->输入---附加依赖项,  加入库名,如: my_API.lib; 或是在c ...

  6. lib库依赖解决

    当前环境之前是装过MySQL官方版本5.6.22,想测试Percona版本MySQL.启动Percona-MySQL报错. [root@dg7 support-files]# /etc/init.d/ ...

  7. .h头文件、 .lib库文件、 .dll动态链接库文件之间的关系

    转自.h头文件. .lib库文件. .dll动态链接库文件之间的关系 h头文件作用:声明函数接口 dll动态链接库作用:含有函数的可执行代码 lib库有两种: (1)静态链接库(Static Liba ...

  8. .h头文件 .lib库文件 .dll动态库文件之间的关系

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  9. LIB库加载方法-引用百度百科

    LIB库加载方法,有三种,如下: 1.LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中\"Add Files to Project\ ...

随机推荐

  1. 自己编写的仿京东移动端的省市联动选择JQuery插件

    概述 什么是插件,插件就是即插即用叫插件,很少的配置,很少的代码就可以用都项目里,之所以做这个插件,是因为做了一个省市区的联动,其他项目如果要用怎么办,难道在ctrl+c,ctrl+v?那样做太low ...

  2. Android Scheme协议与应用全解析

    URL Scheme 的作用 客户端应用可以向操作系统注册一个 URL Scheme,该 Scheme 用于从浏览器或其他应用中启动本应用. 通过指定的 URL 字段,可以让应用在被调起后直接打开某些 ...

  3. Caffe︱构建lmdb数据集、binaryproto均值文件及各类难辨的文件路径名设置细解

    Lmdb生成的过程简述 1.整理并约束尺寸,文件夹.图片放在不同的文件夹之下,注意图片的size需要规约到统一的格式,不然计算均值文件的时候会报错. 2.将内容生成列表放入txt文件中.两个txt文件 ...

  4. Flex中的FusionCharts 3D柱形图

    1.3D柱形图源码 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:f ...

  5. DML 触发器2

    2.行级触发器的关联标识符 :new,:old >>1. 一般通过:new.filed 引用(filed是trigger_table的字段名) :new :old中filed字段的意义 触 ...

  6. Eclipse设置内存大小

    Eclipse设置内存大小 1.修改Eclipse的配置文件 (1)打开Eclipse目录 (2)以EditPlus打开eclipse.ini,修改"-Xms40m  -Xmx512m&qu ...

  7. PyCharm 2017.3 下载与安装

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.下载 (1).下载链接: https://www.jetbrains.com/pycharm ...

  8. 使用everything把一个文件夹里(包含子目录)的所有图片拷贝到另一个文件夹

    最近在找数据集,想要预览数据集里面的全部图片,而因为一些数据集的数据存储方式使得图片都分布在若干层后的子文件里,所以就需要一个如题所示的功能. 找了一堆XCOPY命令的使用方法,差点要撸起袖子写代码干 ...

  9. toggle的用法(点击更换不同的function)当指定元素被点击时,在两个或多个函数之间轮流切换。

    一,用法 <html> <head> <script type="text/javascript" src="/jquery/jquery. ...

  10. 从零一起学Spring Boot之LayIM项目长成记(四) Spring Boot JPA 深入了解

    前言 本篇内容主要是一些关于JPA的常用的一些用法等.内容也是很多是看其他博客学来的,顺道在本系列博客里抽出一篇作为总结.下面让我们来看看吧. 不过我更推荐大家读本篇:https://lufficc. ...