protobuf 中复合数据类型的读写

2023-11-04

背景

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;
 }

在这里插入图片描述

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

protobuf 中复合数据类型的读写 的相关文章

随机推荐

  • 算术逻辑单元

    1 什么是算术逻辑单元 1命名 简称ALU Arithmetic Logic Unit 2组成 ALU有2个单元 1个算术单元和1个逻辑单元 Arithmetic Unit和Logic Unit 3作用 计算机中负责运算的组件 处理数字 逻
  • 基于 BK 树的中文拼写纠错候选召回

    最近在研究中文拼写纠错 在查阅资料的时候看到了这篇文章 从编辑距离 BK树到文本纠错 JadePeng 博客园 觉得 BK 树挺有意思的 决定深入研究一下 并在其基础上重新整理一遍 希望能够对各位读者大大们有所帮助 前置知识 本节介绍实现基
  • vmware下搭建openwrt

    最近闲来无事 想研究下openwrt 所以尝试着自己搭建一个来玩玩 当然这里不是以源码编译的形式 那样太耗时 首先官网下载已有的系统image 路径如下 https archive openwrt org chaos calmer 15 0
  • spring mysql JPA使用autoReconnect=true不生效

    项目里原先使用的是mybatis 使用的mysql配置是 url jdbc mysql xxxx 2400 documentary test useUnicode true characterEncoding UTF 8 autoRecon
  • XXL-JOB 执行器运行报错NoClassDefFoundError HttpObjectAggregator

    xxl job版本为2 3 1 问题描述 执行器启动时不报错 发生任务调度时 任务执行报错如下 2023 04 19 09 35 02 972 WARN nioEventLoopGroup 8 2 i n c ChannelInitiali
  • 2020电赛准备总结(三)

    今天是2020 10 4 现在是下午三点 距离电赛题目发布还有6天 昨天终于完成了追球小车的制作 第一次在csdn上上传视频 不知道怎么上传 想看的可以私信 二维云台 openmv的颜色追踪 这个个人感觉难度还好 不算太难 追踪小车 我做的
  • C#重写List索引器

    C 重写List索引器 using System using System Collections Generic namespace Model
  • 两步彻底解决删除AlibabaProtect

    初见 第一次见这玩意一直占用我的cpu 我试图终止任务发现没有效果 我去服务里面关掉运行发现并没有用 我就知道这不简单 这个阿里巴巴的流氓软件还在扫描我的磁盘 解决 其实要解决很简单 1 C Program Files x86 里有个文件
  • 微信小程序点击按钮弹出弹窗_微信小程序开发弹出框实现方法

    本文主要和大家分享微信小程序开发弹出框实现方法 本文所分享的代码很清晰 希望能帮助到大家 消息提示框 模态弹窗 操作菜单 1 消息提示 wx showToast OBJECT show js 获取应用实例 var app getApp Pa
  • 常用的第三方组件库整理

    一 store 引入localStorage的第三方库 以便于版本兼容 1 下载依赖 yarn add store 2 使用 import store from store 1 store set USER KEY user 保存 2 st
  • 2021-02-08

    学习目标 集合运算 表的加减法和join等 天池龙珠计划SQL训练营 学习内容 4 1表的加减法 4 1 1 什么是集合运算 4 1 2 表的加法 UNION 4 1 2 1 UNION 4 1 2 2UNION 与 OR 谓词 4 1 2
  • ARM Linux 开发板编译字符驱动模块

    ARM Linux 开发板编译字符驱动模块 my driver ko 1 下载源码 源码版本必须和开发板linux内核源码版本号一模一样例如 linux 4 14 111 查看开发板linux版本 uname r 解压 sudo tar z
  • Android Studio 模拟器卡慢、占内存解决方法,kotlinlambda匿名内部类

    一 Android virtual device 自带模拟器Intel 这里讲一下Android Studio 原生模拟器的改善吧 为 Android 模拟器配置硬件加速 Android 模拟器可以使用硬件加速功能来提升性能 有时甚至可以大
  • 一文读懂:全网都在说的AIGC到底是什么?

    什么是AIGC AIGC AI Generated Content 是利用人工智能来生成你所需要的内容 GC的意思是创作内容 与之相对应的概念中 比较熟知的还有PGC 是专业人员用来创作内容 UGC是用户自己创造内容 顾名思义AIGC是利用
  • 需求评审要点

    背景 某功能需要发起需求评审 会议参与人有 产品经理 产品线负责人 前后端开发 架构师 测试 ui等 作为该需求的产品经理主持评审会议 需要注意以下的点 1 需求得理清楚想清楚 若有多个方案 可列出多个方案 且列出自己决定的方案 若未想清楚
  • 52-C语言-文件问题-把字符串中的小写字母变为大写字母,并输出到磁盘文件“test”中,输入的字符串以‘!’结束

    问题 从键盘输入一个字符串 将其中的小写字母全部转换成大写字母 然后输出到一个磁盘文件 test 中保存 输入的字符串以 结束 思路 从键盘输入字符串 char str 100 gets str 将其中的小写字母变为大写字母 并且给大写字母
  • linux查看mysql内存_查看数据库最占资源或内存的查询SQL

    1 使用下面查询修正数据库中最占资源的查询 select b username a DISK READS reads a EXECUTIONS exec a disk reads decode a executions 0 1 a exec
  • MySQL的常用函数大全

    一 字符串函数 常用函数 函数 功能 CONCAT s1 s2 sn 字符串拼接 将s1 s2 sn拼接成一个字符串 LOWER str 将字符串全部转为小写 UPPER str 将字符串全部转为大写 LPAD str n pad 左填充
  • 二、MySQL逻辑架构与常见存储引擎

    1 MySQL逻辑架构 MySQL逻辑架构主要分为3层 如下图所示 1 1 连接层 作用 用于与客户端的连接处理 授权认证 安全 权限校验等 每个客户端连接 在MySQL服务器端都会有一个线程与其相互对应 这个线程负责处理这个客户端连接的操
  • protobuf 中复合数据类型的读写

    背景 protobuf 在生成的 C 代码中为 proto 文件中的每个 message 生成了对应的 C 类 并提供了数据成员的读写方法 message 类型读写 message 示例 message Point double lng 1