[C++][ProtoBuf][Proto3语法][二]详细讲解

目录

  • 1.Any类型
    • 1.说明
    • 2.代码&使用
  • 2.oneof类型
    • 1.说明
    • 2.代码&使用
  • 3.map类型
    • 1.说明
    • 2.代码&使用


1.Any类型

1.说明

  • 字段还可以声明为Any类型,可以理解为泛型类型
    • 使⽤时可以在Any存储任意消息类型
      • 父类是Message
    • Any类型的字段也可以⽤repeated来修饰
  • Any类型是Google已经定义好的类型,其中的include⽬录下查找所有Google已经定义好的.proto⽂件
    • 以我的机器为例ls /usr/include/google/protobuf

2.代码&使用

  • .proto文件
    syntax = "proto3";
    package contacts;
    
    import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
    
    message Address
    {
        string home_address = 1;
        string unit_address = 2;
    }
    
    message PeopleInfo 
    {
        string name = 1;
        int32 age = 2;
        message Phone 
        {
            string number = 1;
            enum PhoneType 
            {
                MP = 0;
                TEL = 1;
            }
        	PhoneType type = 2;
    	}
        repeated Phone phone = 3;
        google.protobuf.Any data = 4;
    }
    
    message Contacts 
    {
    	repeated PeopleInfo contacts = 1;
    }
    
  • 编译生成的CPP代码
    // 新⽣成的 Address 类
    class Address final : public ::PROTOBUF_NAMESPACE_ID::Message 
    {
    public:
        using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
        void CopyFrom(const Address& from);
        using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
        void MergeFrom( const Address& from) 
        {
        Address::MergeImpl(*this, from);
        }
    
        // string home_address = 1;
        void clear_home_address();
        const std::string& home_address() const;
        template <typename ArgT0 = const std::string&, typename... ArgT>
        void set_home_address(ArgT0&& arg0, ArgT... args);
        std::string* mutable_home_address();
        PROTOBUF_NODISCARD std::string* release_home_address();
        void set_allocated_home_address(std::string* home_address);
    
        // string unit_address = 2;
        void clear_unit_address();
        const std::string& unit_address() const;
        template <typename ArgT0 = const std::string&, typename... ArgT>
        void set_unit_address(ArgT0&& arg0, ArgT... args);
        std::string* mutable_unit_address();
        PROTOBUF_NODISCARD std::string* release_unit_address();
        void set_allocated_unit_address(std::string* unit_address);
    };
    
    // 更新的 PeopleInfo 类
    class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message 
    {
    public:
        // .google.protobuf.Any data = 4;
        bool has_data() const;
        void clear_data();
        const ::PROTOBUF_NAMESPACE_ID::Any& data() const;
        PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Any* release_data();
        ::PROTOBUF_NAMESPACE_ID::Any* mutable_data();
        void set_allocated_data(::PROTOBUF_NAMESPACE_ID::Any* data);
    };
    
  • 上述代码中,对于Any字段
    • 设置和获取
      • 获取⽅法的⽅法名称与字段命名完全相同
      • 设置⽅法可以使⽤mutable_⽅法,返回值为Any类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的内容进⾏修改
    • 可以在Any字段中存储任意消息类型,这就要涉及到任意消息类型和Any类型的互转
      • PackFrom():将任意消息类型转为Any类型
      • UnpackTo:将Any类型转回之前设置的任意消息类型
      • Is:用来判断存放的消息类型是否为typename T
      • 这部分代码就在 Google写好的⽂件any.pb.h
        class PROTOBUF_EXPORT Any final : public ::PROTOBUF_NAMESPACE_ID::Message 
        {
        	bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) 
        	{
        		...
        	}
        	
        	bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const 
        	{
        		...
        	}
        	
        	template<typename T> bool Is() const 
        	{
        		return _impl_._any_metadata_.Is<T>();
        	}
        };
        

2.oneof类型

1.说明

  • 如果消息中有很多可选字段, 并且将来同时只有⼀个字段会被设置
    • 那么就可以使⽤oneof加强这个⾏为,也能有节约内存的效果
  • 注意
    • 可选字段中的字段编号,不能与⾮可选字段的编号冲突
    • 不能在oneof中使⽤repeated字段
    • 将来在设置oneof字段中值时,如果将oneof中的字段设置多个,那么只会保留最后⼀次设置的成员,之前设置的oneof成员会⾃动清除

2.代码&使用

  • .proto文件
    syntax = "proto3";
    package contacts;
    
    import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
    
    message Address
    {
        string home_address = 1;
        string unit_address = 2;
    }
    
    message PeopleInfo 
    {
        string name = 1;
        int32 age = 2;
        
        message Phone 
        {
            string number = 1;
            enum PhoneType 
            {
                MP = 0;
                TEL = 1;
            }
        	PhoneType type = 2;
    	}
    	repeated Phone phone = 3;
    	
        google.protobuf.Any data = 4;
        
        // 其他联系⽅式:多选⼀
        oneof other_contact 
        { 
            string qq = 5; 
            string weixin = 6;
        }
    }
    
    message Contacts 
    {
    	repeated PeopleInfo contacts = 1;
    }
    
  • 编译生成的CPP代码
    // 更新的 PeopleInfo 类
    class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message 
    {
        enum OtherContactCase 
        {
            kQq = 5,
            kWeixin = 6,
            OTHER_CONTACT_NOT_SET = 0,
        };
    
        // string qq = 5;
        bool has_qq() const;
        void clear_qq();
        const std::string& qq() const;
        template <typename ArgT0 = const std::string&, typename... ArgT>
        void set_qq(ArgT0&& arg0, ArgT... args);
        std::string* mutable_qq();
        PROTOBUF_NODISCARD std::string* release_qq();
        void set_allocated_qq(std::string* qq);
    
        // string weixin = 6;
        bool has_weixin() const;
        void clear_weixin();
        const std::string& weixin() const;
        template <typename ArgT0 = const std::string&, typename... ArgT>
        void set_weixin(ArgT0&& arg0, ArgT... args);
        std::string* mutable_weixin();
        PROTOBUF_NODISCARD std::string* release_weixin();
        void set_allocated_weixin(std::string* weixin);
        void clear_other_contact();
        OtherContactCase other_contact_case() const;
    };
    
  • 上述的代码中,对于oneof字段
    • 会将oneof中的多个字段定义为一个枚举类型
    • 设置和获取
      • oneof内的字段进⾏常规的设置和获取即可
      • 但要注意只能设置⼀个,如果设置 多个,那么只会保留最后⼀次设置的成员
    • 清空oneof字段:clear_⽅法
    • 获取当前设置了哪个字段:_case⽅法

3.map类型

1.说明

  • 语法⽀持创建⼀个关联映射字段,也就是可以使⽤map类型去声明字段类型,格式
    map<key_type, value_type> map_field = N;
    
  • 注意
    • key_type是除了floatbytes类型以外的任意标量类型
    • value_type可以是任意类型
    • map字段不可以repeated修饰
    • map 中存⼊的元素是⽆序的

2.代码&使用

  • .proto文件
    syntax = "proto3";
    package contacts;
    
    import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
    
    message Address
    {
        string home_address = 1;
        string unit_address = 2;
    }
    
    message PeopleInfo 
    {
        string name = 1;
        int32 age = 2;
        
        message Phone 
        {
            string number = 1;
            enum PhoneType 
            {
                MP = 0;
                TEL = 1;
            }
        	PhoneType type = 2;
    	}
    
    	repeated Phone phone = 3;
    
        google.protobuf.Any data = 4;
    
        // 其他联系⽅式:多选⼀
        oneof other_contact 
        {
            string qq = 5; 
            string weixin = 6;
        }
        
        map<string, string> remark = 7;
    }
    
    
    message Contacts 
    {
    	repeated PeopleInfo contacts = 1;
    }
    
  • 编译生成的CPP文件
    // 更新的 PeopleInfo 类
    class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message 
    {
        // map<string, string> remark = 7;
        int remark_size() const;
        void clear_remark();
        const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >& remark() const;
        ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >* mutable_remark();
    };
    
  • 上述的代码中,对于Map类型的字段
    • 清空map:clear_ ⽅法
    • 设置和获取
      • 获取⽅法的⽅法名称与字段命名完全相同
      • 设置⽅法mutable_⽅法,返回值为Map类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的0内容进⾏修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/784988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter【组件】标签

简介 flutter 标签组件。标签组件是一种常见的 UI 元素&#xff0c;用于显示和管理多个标签&#xff08;或标签集合&#xff09;。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit pub地址&#xff1a;https://pub.dev/packages/jac_uikit 使用方式&…

机器学习:预测评估8类指标

机器学习&#xff1a;8类预测评估指标 R方值、平均值绝对误差值MAE、均方误差MSE、均方误差根EMSE、中位数绝对误差MAD、平均绝对百分误差MAPE、可解释方差分EVS、均方根对数误差MLSE。 一、R方值 1、说明&#xff1a; R方值&#xff0c;也称为确定系数或拟合优度&#xff…

Python 基础知识:为什么使用 __init__.py ?

大家好&#xff01;今天&#xff0c;我们将深入了解 Python 中的 __init__.py 文件&#xff0c;这个小文件却能干大事。让我们抛开任何专业术语&#xff0c;直接进入正题。 什么是 __init__.py &#xff1f; 假设你有一个 Python 目录&#xff0c;里面有一堆 Python 文件&…

从零开始做题:My_lllp

题目 给出一张png图片 解题 ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zulu/My_lllp] └─$ python2 lsb.py extract my_lllp.png out.txt my_lllp [] Image size: 1080x1079 pixels. [] Written extracted data to out.txt. ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zul…

绝区伍--2024年AI发展路线图

2024 年将是人工智能具有里程碑意义的一年。随着新模式、融资轮次和进步以惊人的速度出现&#xff0c;很难跟上人工智能世界发生的一切。让我们深入了解 2024 年可能定义人工智能的关键事件、产品发布、研究突破和趋势。 2024 年第一季度 2024 年第一季度将推出一些主要车型并…

AI绘画Stable Diffusion:ControlNet组件—Scribble(涂鸦)赋予用户精细控制权,让涂鸦草图焕发生命力

大家好&#xff0c;我是画画的小强 今天给大家分享一下AI绘画Stable Diffusion当中的&#xff1a;ControlNet Scribble组件&#xff0c;**Scribble&#xff08;涂鸦&#xff09;**技术是一种能够为用户提供独特的手动注释或标记图像&#xff08;如&#xff1a;涂鸦、简笔画等&…

变阻器的阻值范围是多少?

变阻器&#xff0c;又称可变电阻器或电位器&#xff0c;是一种可以改变电阻值的电子元件。它通常由一个滑动臂、一个固定电阻体和一个滑动触点组成。通过滑动臂在固定电阻体上的位置变化&#xff0c;可以实现对电阻值的连续调整。变阻器广泛应用于各种电子设备中&#xff0c;如…

2024 ACT汽车软件与安全技术周 | 龙智携全方位汽车软件开发解决方案亮相,助力应对汽车软件开发功能安全、合规等挑战

2024年7月18-19日&#xff08;周四-周五&#xff09;&#xff0c;2024第三届ACT汽车软件与安全技术周将在上海佘山翰悦阁酒店举办。 龙智即将携汽车开发及管理解决方案创新亮相&#xff0c;并在汽车信息安全技术峰会主会场上发表主题演讲&#xff0c;分享推动汽车软件开发与功…

Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker

文章目录 Clickhouse基础实操windows docker desktop 下载clickhousespringboot项目配置clickhouse Redis谈下你对Redis的了解&#xff1f;Redis一般都有哪些使用的场景&#xff1f;Redis有哪些常见的功能&#xff1f;Redis支持的数据类型有哪些&#xff1f;Redis为什么这么快…

电源中电感底部需要铺地平面吗?

感有交变电流&#xff0c;电感底部铺铜会在地平面上产生涡流&#xff0c;涡流效应会影响功率电感的电感量&#xff0c;涡流也会增加系统的损耗&#xff0c;同时交变电流产生的噪声会增加地平面的噪声&#xff0c;会影响其他信号的稳定性。 在EMC方面来看&#xff0c;在电感底部…

DSSM双塔特征交互

传统的DSSM双塔无法在早期进行user和item侧的特征交互&#xff0c;这在一定程度上降低了模型性能。我们想要对双塔模型进行细粒度的特征交互&#xff0c;同时又不失双塔模型离线建向量索引的解耦性。下面介绍两篇这方面的工作。 美团-Dual Augmented Two-tower 在user和item的特…

基于stm32开发的红外循迹小车

本项目算是接触32来开发的第一个小项目了&#xff0c;虽然前期用51写过一个循迹小车&#xff0c;以为直接转到32会比较简单&#xff0c;结果还是花了大几天才把小车的参数完全调完&#xff0c;以此来记录下自己的学习历程&#xff08;注&#xff1a;循迹算法并未加入PID算法&am…

AI网络爬虫016:用deepseek批量提取coze扣子的智能体数据

文章目录 一、介绍二、输入内容三、输出内容一、介绍 动态加载页面,返回json数据: 翻页规律: https://www.coze.cn/api/marketplace 这两个URL在多个方面有所不同,主要差异如下: **查询参数(Query Parameters)**: - 第一个URL的查询参数包括: - `entity_type=1` - `…

【VUE基础】VUE3第七节—Vue Router路由基础

Vue Router 是 Vue 官方的客户端路由解决方案。 客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时&#xff0c;URL 会随之更新&#xff0c;但页面不需要从服务器重新加载。 Vue Router 基于 Vue 的组件系统构建&…

imazing电脑怎么下载 imazing怎么下载软件 使用iMazing下载和卸载Apple设备上的应用程序

iMazing官方版是一款管理苹果设备的软件&#xff0c;是一款帮助用户管理 iOS手机的PC端应用程序&#xff0c;能力远超 iTunes 提供的终极 iOS 设备管理器。在iMazing官方版上与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;功能比iTunes更…

rocketmq主从自动切换(Controller 嵌入 NameServer 部署)

rocketmq5以后&#xff0c;加入了主从自动切换的功能&#xff1a; 官网 https://rocketmq.apache.org/zh/docs/deploymentOperations/03autofailover 准备工作 1&#xff09;关闭将要升级的nameserver、master、slave 2&#xff09;复制master的store文件到其他两台机器&a…

240708_昇思学习打卡-Day20-MindNLP ChatGLM-6B StreamChat

240708_昇思学习打卡-Day20-MindNLP ChatGLM-6B StreamChat 基于MindNLP和ChatGLM-6B实现一个聊天应用&#xff0c;本文进行简单记录。 环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mi…

通过高德地图 JS API实现单击鼠标进行标注

效果图: 核心代码: <template><a-modal title="选择地图所在位置" :width="width" :visible="visible" @ok="handleOk" @cancel="handleCancel" cancelText="关闭"><div class="location-…

Flutter——最详细(Badge)使用教程

背景 主要常用于组件叠加上圆点提示&#xff1b; 使用场景&#xff0c;消息数量提示&#xff0c;消息红点提示 属性作用backgroundColor红点背景色smallSize设置红点大小isLabelVisible是否显示offset设置红点位置alignment设置红点位置child设置底部组件 代码块 class Badge…

【Elasticsearch】开源搜索技术的演进与选择:Elasticsearch 与 OpenSearch

开源搜索技术的演进与选择&#xff1a;Elasticsearch 与 OpenSearch 1.历史发展2.OpenSearch 与 Elasticsearch 相同点3.OpenSearch 与 Elasticsearch 不同点3.1 版本大不同3.2 许可证不同3.3 社区不同3.4 功能不同3.5 安全性不同3.6 性能不同3.7 价格不同3.8 两者可相互导入 4…