当前位置: 首页 > news >正文

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

目录

  • 1.字段规则
  • 2.消息类型的定义与使用
    • 1.定义
    • 2.使用
  • 3.enum类型
    • 1.语法
    • 2.定义时注意
    • 3.代码


1.字段规则

  • 消息的字段可以⽤下⾯⼏种规则来修饰
    • singular:消息中可以包含该字段零次或⼀次(不超过⼀次)
      • proto3语法中,字段默认使⽤该规则
    • repeated消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留
      • 可以理解为定义了⼀个数组
  • 示例:表示一个通讯录里有多个人的信息
    message Contacts
    {repeated PeopleInfo contacts = 1;
    }
    

2.消息类型的定义与使用

1.定义

  • 在单个.proto⽂件中可以定义多个消息体,且⽀持定义嵌套类型的消息(任意多层)
    • 每个消息体中的字段编号可以重复
  • 更新contacts.proto,可以将phone_number提取出来,单独成为⼀个消息
    // -------------------------- 嵌套写法 -------------------------
    syntax = "proto3";
    package contacts;message PeopleInfo 
    {string name = 1; int32 age = 2; message Phone {string number = 1;}
    }
    // -------------------------- ⾮嵌套写法 ------------------------
    syntax = "proto3";
    package contacts;message Phone 
    {string number = 1;
    }message PeopleInfo 
    {string name = 1; int32 age = 2; 
    }
    

2.使用

  • 消息类型可作为字段类型使用
    syntax = "proto3";
    package contacts;// 联系⼈
    message PeopleInfo 
    {string name = 1; int32 age = 2; message Phone {string number = 1; }repeated Phone phone = 3; 
    }
    
  • 可导入其他.proto文件的消息并使用import导入
    syntax = "proto3";
    package contacts;
    import "phone.proto"; // 使⽤ import 将 phone.proto ⽂件导⼊进来message PeopleInfo 
    {string name = 1; int32 age = 2; // 引⼊的⽂件声明了package,使⽤消息时,需要⽤ ‘命名空间.消息类型’ 格式 repeated phone.Phone phone = 3; 
    }
    
  • 注意:在proto3⽂件中可以导⼊proto2消息类型并使⽤它们,反之亦然
  • 说明
    • 每个字段都有⼀个clear_⽅法,可以将字段重新设置回empty状态
    • 每个字段都有设置和获取的⽅法, 获取⽅法的⽅法名称与字段命名完全相同
      • 但如果是消息类型的字段,其设置⽅法为mutable_⽅法,返回值为消息类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的内容进⾏修改
        • mutable -> 访问和修改消息字段中的嵌套消息
    • 对于使⽤repeated修饰的字段,也就是数组类型,pb为用户提供:
      • add_⽅法来新增⼀个值
      • _size⽅法来判断数组存放元素的个数

3.enum类型

1.语法

  • 语法
    enum Type
    {}
    
  • 注意
    • 0值常量必须存在,且要作为第⼀个元素
      • 这是为了与proto2的语义兼容:第⼀个元素作为默认值,且值为0
    • 枚举类型可以在消息外定义,也可以在消息体内定义(嵌套)
    • 枚举的常量值在32位整数的范围内
      • 负值⽆效,所以不建议使⽤负值

2.定义时注意

  • 将两个"具有相同枚举值名称"的枚举类型放在单个.proto⽂件下测试时,编译后会报错:某某某常量已经被定义,所以这⾥要注意
    • 同级(同层)的枚举类型,各个枚举类型中的常量不能重名
      enum PhoneType 
      {MP = 0;TEL = 1;
      }
      enum PhoneTypeCopy 
      {MP = 0; // ERROR:MP 已经定义	
      }
      
    • 单个.proto⽂件下,最外层枚举类型和嵌套枚举类型,不算同级
      enum PhoneTypeCopy 
      {MP = 0; // ⽤法正确
      }message Phone 
      {string number = 1;enum PhoneType {MP = 0;TEL = 1;}
      }
      
    • 多个.proto⽂件下,若⼀个⽂件引⼊了其他⽂件,且每个⽂件都未声明package,每个proto⽂件中的枚举类型都在最外层,算同级
      // phone1.proto
      import "phone1.proto"
      enum PhoneType 
      {MP = 0; // ERROR:MP 已经定义TEL = 1; 
      }// phone2.proto
      enum PhoneTypeCopy 
      {MP = 0;
      }
      
    • 多个.proto⽂件下,若⼀个⽂件引⼊了其他⽂件,且每个⽂件都声明了package,不算同级
      // phone1.proto
      import "phone1.proto"
      package phone1;
      enum PhoneType 
      {MP = 0; // ⽤法正确TEL = 1;
      }// phone2.proto
      package phone2;
      enum PhoneTypeCopy 
      {MP = 0;
      }
      

3.代码

  • 编译生成的CPP代码
    // 新⽣成的 PeopleInfo_Phone_PhoneType 枚举类
    enum PeopleInfo_Phone_PhoneType : int 
    {PeopleInfo_Phone_PhoneType_MP = 0,PeopleInfo_Phone_PhoneType_TEL = 1,PeopleInfo_Phone_PhoneType_PeopleInfo_Phone_PhoneType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),PeopleInfo_Phone_PhoneType_PeopleInfo_Phone_PhoneType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
    };// 更新的 PeopleInfo_Phone 类
    class PeopleInfo_Phone final : public ::PROTOBUF_NAMESPACE_ID::Message 
    {
    public:typedef PeopleInfo_Phone_PhoneType PhoneType;static inline bool PhoneType_IsValid(int value) {return PeopleInfo_Phone_PhoneType_IsValid(value);}template<typename T>static inline const std::string& PhoneType_Name(T enum_t_value) {...}static inline bool PhoneType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, PhoneType* value) {...}// .contacts.PeopleInfo.Phone.PhoneType type = 2;void clear_type();::contacts::PeopleInfo_Phone_PhoneType type() const;void set_type(::contacts::PeopleInfo_Phone_PhoneType value);
    };
    
  • 上述的代码中
    • 对于在.proto⽂件中定义的枚举类型,编译⽣成的代码中会含有
      • 与之对应的枚举类型
      • 校验枚举值是否有效的⽅法_IsValid
      • 以及获取枚举值名称的⽅法_Name
    • 对于使⽤了枚举类型的字段,包含设置和获取字段的⽅法,已经清空字段的⽅法clear_
http://www.lryc.cn/news/395269.html

相关文章:

  • 千古雄文《渔樵问对》原文、译文、解析
  • uniapp 开发备忘录-防坑指南
  • Simple_ReAct_Agent
  • window wsl安装ubuntu
  • postmessage()在同一域名下,传递消息给另一个页面
  • 初始redis:在Ubuntu上安装redis
  • 生物素结合金纳米粒子(Bt@Au-NPs ) biotin-conjugated Au-NPs
  • LeetCode热题100刷题9:25. K 个一组翻转链表、101. 对称二叉树、543. 二叉树的直径、102. 二叉树的层序遍历
  • PyJWT,一个基于JSON的轻量级安全通信方式的python库
  • Golang | Leetcode Golang题解之第223题矩形面积
  • 新手怎么使用GitLab?
  • 表情包原理
  • 技术难点思考SpringBoot如何集成Jmeter开发
  • 如何快速使用C语言操作sqlite3
  • 网络模型介绍
  • Codeforces Round #956 (Div. 2) and ByteRace 2024
  • 域名、网页、HTTP概述
  • Redisson分布式锁、可重入锁
  • 适合宠物饮水机的光电传感器有哪些
  • 『Python学习笔记』Python运行设置PYTHONPATH环境变量!
  • 2024年06月CCF-GESP编程能力等级认证Python编程三级真题解析
  • 代码随想录算法训练营:20/60
  • Apache Seata应用侧启动过程剖析——RM TM如何与TC建立连接
  • Origin 的使用
  • MySQL相关知识点
  • 第4章 Vite模块化与插件系统(二)
  • 前端传到后端的data数组中有些属性值为空
  • 怎么批量下载网页里的图片和视频 如何批量下载一个网站的所有图片 如何批量下载网页视频文件 idm软件怎么下载
  • Python面试题:在 Python 中,如何处理文件操作?
  • 红日靶机1