c++读取protobuf里的map字段或嵌套message字段



首先需要了解, map字段是个语法糖, 比如 node_def.proto中的如下部分:
...
import "tensorflow/core/framework/attr_value.proto";
...
message NodeDef {
  string name = 1;
  string op = 2;
  repeated string input = 3;
  string device = 4;
  map<string, AttrValue> attr = 5;
};
最后一个map 其实是相当于一个嵌套的 repeated message:
message NodeDef {
  string name = 1;
  string op = 2;
  repeated string input = 3;
  string device = 4;


  message attrEntry {
    string key = 1;
    AttrValue value = 2;
  }


  repeated attrEntry attr = 5;
};




此处应该用到protobuf反射:  部分代码如下:


void getattrvalue_bykey( const tensorflow::NodeDef &node,  string needed_attrkey  ,ReturnStruct &returnstruct  ) {
     if (needed_attrkey.size()> 0 ) {
         // **1** : 从传入目标层 的attr属性中读信息
         const google::protobuf::Reflection* pNodeReflection   = node.GetReflection();
         const google::protobuf::Descriptor* pNodeDescriptor   = node.GetDescriptor();
         const google::protobuf::FieldDescriptor* pAttrField   = pNodeDescriptor->FindFieldByName("attr");


         for (int j = 0; j < node.attr_size(); ++j ) {     
             NodeDef::NodeDef_AttrEntry attrentry ;
             attrentry.MergeFrom( pNodeReflection->GetRepeatedMessage(node,  pAttrField , j  ) );


             auto pAttrentryReflection  = attrentry.GetReflection();
             auto pAttrentryDescriptor  = attrentry.GetDescriptor();
             auto pAttrkey_field        = pAttrentryDescriptor->FindFieldByName("key");
             auto pAttrValue_field      = pAttrentryDescriptor->FindFieldByName("value");


             if ( needed_attrkey == "strides") {
                 //strides  < == > attr的key为 "strides"   值为list 的第二和第三维。
                 if ( "strides" == pAttrentryReflection->GetString(attrentry , pAttrkey_field) ) {
                     ::tensorflow::AttrValue attrvalue;
                     attrvalue.MergeFrom( pAttrentryReflection->GetMessage(attrentry, pAttrValue_field ) );
                     auto pAttrvalueReflection = attrvalue.GetReflection();
                     auto pAttrvalueDescriptor = attrvalue.GetDescriptor();


                     // **2** : 从attr的 attrvalue属性中 读list信息
                     auto pListvalue_field       = pAttrvalueDescriptor->FindFieldByName("list");
                     ::tensorflow::AttrValue_ListValue listvalue ;
                     listvalue.MergeFrom(pAttrvalueReflection->GetMessage(attrvalue, pListvalue_field ) );
                     auto pListvalueReflection   = listvalue.GetReflection();
                     auto pListvalueDescriptor   = listvalue.GetDescriptor();
                     auto pIntegervalue_field    = pListvalueDescriptor->FindFieldByName("i");
                     //TODO: "strides" 值为list 的第二和第三维。 假设现在这两维的值是一样的。如果不一样,将来再处理
                     returnstruct.intvalue       = pListvalueReflection->GetRepeatedInt64(listvalue, pIntegervalue_field, 1 );
                     if (returnstruct.intvalue  != pListvalueReflection->GetRepeatedInt64(listvalue, pIntegervalue_field, 2 ) ) {
                        cout << "!!warning!  the width and hight strides is not equal !! now only use one !!" << endl;
                     }
                 }
             }
        }
    }
}



C++读取Protobuf数据,你需要按照以下步骤进行操作: 1. 首先,确保你已经安装了Protobuf库并且已经生成了对应的C++代码文件。你可以使用Protobuf的编译器protoc来生成这些代码文件。例如,假设你的.proto文件名为example.proto,则可以使用以下命令生成C++代码文件: ``` protoc -I=<proto文件目录> --cpp_out=<输出目录> example.proto ``` 这将生成一个example.pb.h头文件和一个example.pb.cc源文件。 2. 在你的C++项目中包含生成的头文件example.pb.h,并确保项目能够找到对应的源文件example.pb.cc。 3. 创建一个用于读取Protobuf数据的输入流,并打开你的Protobuf数据文件。例如: ```cpp #include <fstream> #include "example.pb.h" // ... std::ifstream input("data.bin", std::ios::in | std::ios::binary); if (!input) { // 处理文件打开失败的情况 return -1; } ``` 4. 使用Protobuf提供的函数从输入流中读取数据并解析为Protobuf对象。例如,如果你的Protobuf消息类型为ExampleMessage,则可以使用以下代码进行解析: ```cpp ExampleMessage message; if (!message.ParseFromIstream(&input)) { // 处理解析失败的情况 return -1; } ``` 5. 现在,你可以使用message对象访问读取到的Protobuf数据的字段了。根据你的Protobuf定义,使用message中的成员函数来获取字段的值。例如,如果你的message有一个名为name的字符串字段,则可以使用以下代码获取其值: ```cpp std::string name = message.name(); ``` 这样,你就可以在C++中成功读取Protobuf数据了。记得根据你的实际情况进行相应的修改和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值