当前位置:网站首页>protobuf 中复合数据类型的读写
protobuf 中复合数据类型的读写
2022-07-30 04:33:00 【litanyuan】
背景
protobuf 在生成的 C++ 代码中为 .proto 文件中的每个 message 生成了对应的 C++ 类,并提供了数据成员的读写方法。
message 类型读写
①.message 示例
message Point
{
double lng = 1;
double lat = 2;
}
message DemoMsg
{
int32 id = 1;
Point pos = 2;
}
②.成员赋值
通过 mutable_xxx 方法返回的指针给成员赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.mutable_pos()->set_lng(112.56);
msg.mutable_pos()->set_lat(56.78);
cout << msg.DebugString() << endl;

通过 copyFrom 方法使用结构体赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
msg.mutable_pos()->CopyFrom(m_p);
cout << msg.DebugString() << endl;
通过 set_allocated_xxx 成员函数传入指针进行赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
protoTest::Point * m_p = new protoTest::Point;
m_p->set_lng(112.56);
m_p->set_lat(56.78);
msg.set_allocated_pos(m_p);
cout << msg.DebugString() << endl;
③.成员读取
通过成员函数 has_xxx 可以判断 message 类型的成员是否被赋值。
protoTest::Point* m_p = new protoTest::Point;
m_p->set_lng(112.56);
m_p->set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_allocated_pos(m_p);
if (msg.has_pos())
{
auto& pos = msg.pos();
cout << pos.lng() << " " << pos.lat();
}

map 类型读写
①.message 示例
message DemoMsg
{
map<int32,string> a = 1;
}
②.成员赋值
map 类型成员赋值需通过 mutable_xxx 方法进行:
protoTest::DemoMsg msg;
msg.mutable_a()->insert({
1,"aaaaa" });
msg.mutable_a()->insert({
2,"bbbbb" });
msg.mutable_a()->insert({
3,"ccccc" });
cout << msg.DebugString() << endl;

③.成员读取
protoTest::DemoMsg msg;
msg.mutable_a()->insert({
1,"aaaaa" });
msg.mutable_a()->insert({
2,"bbbbb" });
auto map = msg.mutable_a();
if (map->contains(1))
{
cout << map->at(1) << endl;
}

any 类型读写
①.概述
any 可以保存任意的已知类型的序列化数据,常用于对结构体数据的再包装,即可以把不同类型的 message 包装在同一个 message 中进行传输。
②.message 示例
syntax = "proto3";
import "google/protobuf/any.proto";
package protoTest;
message Point
{
double lng = 1;
double lat = 2;
}
message Node
{
int32 id = 1;
string name = 2;
}
message DemoMsg
{
int32 id = 1;
google.protobuf.Any data = 2;
}
③.成员赋值
使用 any 类型的成员函数 PackFrom 来进行赋值。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(1);
msg.mutable_data()->PackFrom(m_p);
cout << msg.DebugString() << endl;

④.message 类型判断
通过成员函数 Is 可以判断是否为指定类型的数据。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::Node m_node;
m_node.set_id(1);
m_node.set_name("Zhangsan");
protoTest::DemoMsg msg1;
msg1.set_id(1);
msg1.mutable_data()->PackFrom(m_p);
protoTest::DemoMsg msg2;
msg2.set_id(2);
msg2.mutable_data()->PackFrom(m_node);
auto checkAny = [&](const protoTest::DemoMsg& msg) {
if (msg.data().Is<protoTest::Point>())
cout << " msgID:" << msg.id() << " 中 data 类型为 Point " << endl;
else if( msg.data().Is<protoTest::Node>() )
cout << " msgID:" << msg.id() << " 中 data 类型为 Node " << endl;
};
checkAny(msg1);
checkAny(msg2);

⑤.成员读取
通过成员函数 UnpackTo 可以把 any 数据还原成对应的结构体数据。
protoTest::Point m_p;
m_p.set_lng(112.56);
m_p.set_lat(56.78);
protoTest::DemoMsg msg;
msg.set_id(1);
msg.mutable_data()->PackFrom(m_p);
if (msg.data().Is<protoTest::Point>())
{
protoTest::Point pos;
if (msg.data().UnpackTo(&pos))
{
cout << pos.DebugString() << endl;
}
}

oneof 类型读写
①.概述
oneof 类型同 C++ 中的 union 类型,同一时刻只有一种类型有效。
②.message 示例
message DemoMsg
{
oneof test{
int32 id = 1;
string name =2;
};
}
③.成员赋值
直接使用 set_xxx 给相应的成员赋值即可,但只有最后一次赋值的数据有效。
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
cout << msg.DebugString() << endl;
④.数据类型判断
通过 has_xxx 方法判断对应类型成员是否赋值:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
if (msg.has_name())
{
cout << "msg 中为 string 类型" << endl;
}

通过 xxx_case 方法当前判断保存的成员类型:
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
switch (msg.test_case())
{
case protoTest::DemoMsg::kId:
cout << "msg 中为 int32 类型" << endl; break;
case protoTest::DemoMsg::kName:
cout << "msg 中为 string 类型" << endl; break;
default:
break;
}
⑤.成员读取
先判断当前保存的字段类型,再读取数据。
protoTest::DemoMsg msg;
msg.set_id(100);
msg.set_name("123");
switch (msg.test_case())
{
case protoTest::DemoMsg::kId:
cout << msg.id() << endl; break;
case protoTest::DemoMsg::kName:
cout << msg.name() << endl; break;
default:
break;
}


边栏推荐
猜你喜欢

Unity beginner 5 cameras follow, border control and simple particle control (2 d)
Go study notes (84) - Go project directory structure

1. 获取数据-requests.get()

在麒麟V10操作系统上安装MySQL数据库

See you in shenzhen!Cloud native to accelerate the application building special: see cloud native FinOps, SRE, high-performance computing scenario best practices

2.4 hill sorting

基于OpenCV实现的图像拼接(配准)案例
![[MRCTF2020]Hello_ misc](/img/ea/0faacf6e544b60e3459d8ace4d5f42.png)
[MRCTF2020]Hello_ misc

恐造成下一个“千年虫”的闰秒,遭科技巨头们联合抵制
![[MRCTF2020]Hello_misc](/img/ea/0faacf6e544b60e3459d8ace4d5f42.png)
[MRCTF2020]Hello_misc
随机推荐
@WebServlet注解(Servlet注解)
获取本机IP和Request的IP
Data Lake: Data Integration Tool DataX
PyG搭建R-GCN实现节点分类
Go study notes (84) - Go project directory structure
sql语句-如何以一个表中的数据为条件据查询另一个表中的数据
Reverse Theory Knowledge 3 [UI Modification]
The VUX Datetime component compute-days-function dynamically sets the date list
Discourse 自定义头部链接(Custom Header Links)
成为一个合格的网安,你知道这些吗?
LeetCode 114. Expand Binary Tree into Linked List (One Question Three Eats)
2.6 Radix sort (bucket sort)
Shanxi group (enterprises) in the second network security skills competition part problem WP (7)
golang八股文整理(持续搬运)
Go study notes (84) - Go project directory structure
Many overseas authoritative media hotly discuss TRON: laying the foundation for the decentralization of the Internet
MySql 怎么查出符合条件的最新的数据行?
MySQL installation error solution
Drools (7): WorkBench
MNIST of Dataset: MNIST (handwritten digital image recognition + ubyte.gz file) data set introduction, download, usage (including data enhancement) detailed guide