protobuf中的message数据结构简明教程
【摘要】 介绍如何对如何对protobuf中的message结构进行数据操作。关于protobuf和message数据结构的概念介绍,来源于https://www.jianshu.com/p/b723053a86a6和https://zhuanlan.zhihu.com/p/25174418 。
参考资料:https://www.jianshu.com/p/b723053a86a6 // protobuf定义
https://zhuanlan.zhihu.com/p/25174418 // message结构描述
Protobuf是什么
Protobuf实际是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。
message结构:
Protobuf通过定义message数据结构来进行使用。
- 在一个proto文件中可以包含多个message定义,message之间可以互相引用,message还可以嵌套message和枚举类;
- 一个message通常包含一至多个字段;
- 每个字段包含以下几个部分:字段描述符(可选)、字段类型、字段名称和字段对应的Tag;
字段描述符
字段描述符用于描述字段出现的频率,有以下两个可选值:
- singular:表示出现0次或1次;如果没有声明描述符,默认为singular;
- repeated:表示出现0次或多次;
字段类型
- 基本数据类型:包括double、float、bool、string、bytes、int32、int64、uint32、uint64、sint32、sint64、fixed32、fixed64、sfixed32、sfixed64;
- 引用其他message类型;
- 枚举类型:对于枚举类型,protobuf有个约束:枚举的第一项对应的值必须为0;
如下为一个message结构例子:
packeage MxTools;
message MxpiClass
{
repeated MxpiMetaHeader headerVec = 1;
int32 classId = 2;
string className = 3;
float confidence = 4;
}
message MxpiMetaHeader
{
string parentName = 1;
int32 memberId = 2;
string dataSource = 3;
}
- 在MxpiClass这个数据结构中,嵌套了另一个message类型(MxpiMetaHeader)。
- repeated声明该字段是可出现多次的。
- 每个message里面的字段都有对应的Tag值,且Tag必须是唯一数字。Tag主要用于说明字段在二进制文件的对应关系,一旦指定字段为对应的Tag,不应该在后续进行变更;
如何对message数据结构进行数据操作
下面,我们以MxpiClass为例子说明如何对message数据结构进行操作。
代码如下:
int main(int argc, char* argv[])
{
MxpiClass mxpiClass;
// 对int类型字段赋值
mxpiClass.set_classid(1); //
// 对string类型字段赋值
mxpiClass.set_classname("MyMxpiClass");
// 对repeated 类型字段赋值的方法.
// 首先需要通过add_headervec()创建一个header_1,
// 通过对header_1的赋值来实现赋值操作
// 注意:此时的header_1是指针
MxpiMetaHeader* header_1 = mxpiClass.add_headervec();
header_1->set_datasource("myDataSource_1");
header_1->set_memberid(1);
// 对repeated类型数据的查看,查看第一个headerVec
cout << mxpiClass.headervec(0).datasource()<<endl;
cout << mxpiClass.headervec(0).memberid()<<endl;
// 添加第二个headerVec
MxpiMetaHeader* header_2 = mxpiClass.add_headervec();
header_2->set_datasource("myDataSource_2");
header_2->set_memberid(2);
// 查看第二个headerVec
cout << mxpiClass.headervec(1).datasource()<<endl;
cout << mxpiClass.headervec(1).memberid()<<endl;
// 输出mxpiClass的数据结构
cout<< "MxpiClass {\n"<<mxpiClass.DebugString() <<"}"<<endl;
return 0;
}
最后,采用DebugString()方法,显示mxpiClass的数据结构如下:
MxpiClass {
headerVec {
memberId: 1
dataSource: "myDataSource_1"
}
headerVec {
memberId: 2
dataSource: "myDataSource_2"
}
classId: 1
className: "MyMxpiClass"
}
嵌套message数据结构的数据操作:如果一个message结构嵌套了另一个message结构,如下所示:
message MxpiVision
{
repeated MxpiMetaHeader headerVec = 1;
MxpiVisionInfo visionInfo = 2;
MxpiVisionData visionData = 3;
}
message MxpiVisionData
uint64 dataPtr = 1;
int32 dataSize = 2;
uint32 deviceId = 3;
MxpiMemoryType memType = 4;
uint64 freeFunc = 5;
bytes dataStr = 6;
}
enum MxpiMemoryType {
MXPI_MEMORY_HOST = 0;
MXPI_MEMORY_DEVICE = 1;
MXPI_MEMORY_DVPP = 2;
}
在MxpiVision中嵌套了MxpiVsionData,如下代码示例如何对MxpiVsionData进行赋值。
int main(int argc, char* argv[])
{
MxpiVision mxpiVsion;
// 使用mutable方法新建一个MxpiVisionData数据类型,通过对Data赋值实现。
MxpiVisionData* Data = mxpiVsion.mutable_visiondata();
Data->set_dataptr(123456);
Data->set_deviceid(1);
// 对enum类型的字段赋值示例
Data->set_memtype(MXPI_MEMORY_HOST);
return 0;
}
总结:
- 对于singular类的字段:
- 基本数据类型的字段,通过“set_字段名()”方式进行赋值。
- 对于嵌套的message字段,通过“mutable_字段名()”,新建一个该类数据结构,然后进行赋值。
- 对repeated字段:
- 基本数据类型,通过“add_字段名()”,进行赋值,例如add_num(2)。(num为int型字段)
- 对于嵌套的message字段,通过“add_字段名()”,添加一个该类的数据结构,然后进行赋值。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)