《protobuf》基础语法2

news2025/1/25 4:44:18

文章目录

  • 枚举类型
  • ANY 类型
  • oneof 类型
  • map 类型
  • 改进通讯录实例

枚举类型

protobuf里有枚举类型,定义如下

enum PhoneType
{
	string home_addr = 0;
	string work_addr = 1;
}

message一样,可分为 嵌套定义,文件内定义,文件外定义。不过多演示

但是值得注意的点是

  1. 同级(同层)的枚举类型,各个枚举类型中的常量不能重名,否则编译会报错。如下:
enum A
{
	int32 a = 0;
}
enum B
{
	int32 a = 0;
}

A和B有相同的变量a,所以会报错

  1. 单个 .proto 文件下,最外层枚举类型和嵌套枚举类型,不算同级。如下:
enum A
{
	int32 a = 0;
}
message C
{
	enum B
	{
		int32 a = 0;
	}
}
  1. 多个 .proto 文件下,若一个文件引入了其他⽂件,且每个文件都未声明 package,每个 proto 文
    件中的枚举类型都在最外层,算同级。如下:
// 在 A.proto 文件里
import "B.proto"
enum A
{
	int32 a = 0;   // 报错,B.proto 里以及定义
}
-----------------------
// 在 B.proto 文件里
enum B
{
	int32 a = 0;
}
  1. 多个 .proto 文件下,若一个文件引入了其他文件,且每个文件都声明了 package,不算同级。如下
// 在 A.proto 文件里
import "B.proto"
package A;
enum A
{
	int32 a = 0;
}
-----------------------
// 在 B.proto 文件里
package B;
enum B
{
	int32 a = 0;
}

ANY 类型

介绍一下ANY类型,ANY类型表示任意类型

  • 头文件位置 /usr/local/protobuf/include/google/protobuf/
    在这里插入图片描述

如何将其引入 .proto 文件里

// 在/usr/local/protobuf/include
import "google/protobuf/any.proto";
// 使用
message Any{
	google.protobuf.Any data = 1;
}
  • 介绍常用函数:
// 已知信息如下
/ contacts.proto文件  //
syntax = "proto3"
package contacts;
import "google/protobuf/any.proto";  // 引入Any类型
message PeopleInfo
{
	// 可以用于任何类型的any
	google.protobuf.Any data = 1;
}

message Address
{
	string home_addr;
}

 test.cc文件 //
#include <iostream>
#include "contacts.pb.h"  // contacts.proto 编译后生成的头文件
using namespace std;

int main()
{
    // 包装
	contact2::PeopleInfo people;
	contact2::Address addr;
	addr.set_home_addr("中国");
	google::protobuf::Any* any = people.mutable_data();  // 开辟一段any对象的空间
    any->PackFrom(addr);  // 将addr打包成Any类型

    // 转换
    contact2::Address addr2;
    if(people.has_data())
    {
        google::protobuf::Any any = people.data();  // 获取people里的Any类对象 
        if(any.Is<contact2::Address>()) // 判断any类型是否为 Address 类
        {
            any.UnpackTo(&addr2);  // 输出型参数,填充add2
            cout << addr2.home_addr() << endl;  // 打印
        }
    }
    
	return 0;
}

编译 .proto 文件,然后编译连接 test.cc 文件,执行结果如下:
在这里插入图片描述

执行大致流程
在这里插入图片描述
分类讲解一下常用函数:

  • 属于people对象的
    • Any* mutable_data(); ------- // 开辟一段 any 对象的空间
    • Any& data() const; ----------- // 获得 any 对象(即:people里的data)
    • bool has_data() const; ------- // 判断有无对 any 对象赋值
  • 属于 people 里 Any类型的data 对象的
    • bool PackFrom(const Message& message); -------- // 将任意类型转换成 Any 类
    • bool UnpackTo(Message* message) const; -------- // 将 any 对象里的值赋给相对应类型的对象
    • template< class T> bool Is() const; -------- // 判断是否为对应类型

oneof 类型

oneof 类型语法简单:

  • 定义如下
message PeopleInfo
{
	string name = 1;
	oneof gender
	{
		string male = 2;
		string female = 3;
	}
}

但是值得注意的点是

  • 可选字段中的字段编号,不能与非可选字段的编号冲突。
  • 不能在 oneof 中使用 repeated 字段。
  • 将来在设置 oneof 字段中值时,如果将 oneof 中的字段设置多个,那么只会保留最后⼀次设置的成员,之前设置的 oneof 成员会自动清除。

看看编译后的 .pb.h 文件里定义的内容

class PeopleInfo final :
    public ::PROTOBUF_NAMESPACE_ID::Message 
{
	enum GenderCase 
	{
	 kMale = 2,
	 kFemale = 3,
	 GENDER_NOT_SET = 0,
	};

  // string male = 2;
  bool has_male() const;
  void clear_male();
  const std::string& male() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_male(ArgT0&& arg0, ArgT... args);
  std::string* mutable_male();
  PROTOBUF_NODISCARD std::string* release_male();
  void set_allocated_male(std::string* male);

  // string female = 3;
  bool has_female() const;
  void clear_female();
  const std::string& female() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_female(ArgT0&& arg0, ArgT... args);
  std::string* mutable_female();
  PROTOBUF_NODISCARD std::string* release_female();
  void set_allocated_female(std::string* female);

  void clear_gender();
  GenderCase gender_case() const;
}

会将 oneof 中的多个字段定义为⼀个枚举类型。

  • 设置和获取:对 oneof 内的字段进⾏常规的设置和获取即可,但要注意只能设置⼀个。如果设置多个,那么只会保留最后⼀次设置的成员
  • 清空oneof字段:clear_ 方法
  • 获取当前设置了哪个字段:_case 方法
  • 设置值方法: set_
  • 判断该值是否存在方法:has_

map 类型

类似于C++里面的 map 类型,protobuf自己实现了一个类似的数据结构,protobuf 的 map 类型的实现是基于它的 Message 类型的。

  • 定义如下
message PeopleInfo
{
	map<string, string> info = 1;
}

但是值得注意的点是

repeated map< key_type, value_type> map_name = N;

  • key_type 是除了 float 和 byte 的其他任何标量类型。value_type 可以是任意类型
  • map 也不可以被 repeated 修饰
  • map 中存入的元素是无序

讲解一下几个相关常用函数

  • 在PeopleInfo对象里,一般用 mutable_info ( 这里的 info 是对应map类对象 info ) 来开辟一段空间,返回 map 指针来操控info。
    函数原型Map< std::string, std::string >*mutable_info()
  • void clear_info(); 清空对象里的内容。

此外,map还支持迭代器,和C++里的 unorderedmap 十分类似。

改进通讯录实例

运用上述知识点,对上一篇的通讯录代码进行增添功能

contacts.proto

syntax = "proto3";
package contact2;

// 在/usr/local/protobuf/include
import "google/protobuf/any.proto";

// 地址信息
message Address
{
    string home_addr = 1;
    string work_addr = 2;
}
// 个人信息
message PeopleInfo
{
    string name = 1;
    int32 age = 2;
    // 嵌套定义
    message Phone{
        string number = 1;
        // 嵌套枚举
        enum PhoneType{
            MP = 0;  // 移动电话
            TEL = 1; // 固定电话
        }
        PhoneType type = 2;
    }
    // repeated 修饰词 修饰的变量相当于数组
    repeated Phone phone = 3;
    google.protobuf.Any data = 4;
    // 其他联系方式
    oneof other_contacts
    {
        string QQ = 5;
        string Wechat = 6;
    }
    // 备注
    map<string, string> remark = 7;
}

// 通讯录
message Contacts
{
    repeated PeopleInfo contacts = 1;
}

write.cpp
在这里插入图片描述

执行结果

在这里插入图片描述

read.cpp

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二维码智慧门牌管理系统:智能化地址管理,提升社会治理效率

文章目录 前言一、地址管理挑战二、二维码智慧门牌管理系统解决方案 前言 随着科技的飞速发展&#xff0c;我们的生活正经历前所未有的变革。尤其是智能化技术&#xff0c;已经深刻影响了我们的日常生活和工作环境。然而&#xff0c;在某些领域&#xff0c;如地址管理和社会治…

十大免费好用的视频软件推荐,新手小白必备

很多人都在使用视频软件进行编辑&#xff0c;那么你们知道哪些视频软件是免费的而且还好用&#xff1f; 现在很多小伙伴比较喜欢用手机编辑视频&#xff0c;而这些剪辑软件具有领先的智能化AI技术&#xff0c;让你不用绿幕就能一键挖出图像&#xff0c;不仅可以一键挖出三维人…

获取板块分类并展示

板块分类也会变动&#xff0c;偶尔看下&#xff0c;利于总体分析大盘 https:dapanyuntu.com/ 该网站含有板块信息 分析接口 搜素关键字 拷贝curl到curl解析工具&#xff0c;去掉无用的参数&#xff0c;生成requests代码 尝试nginx反代接口 server {listen 443;loca…

汇率失守7.3关口

号外&#xff1a;9.8教链内参《被判入狱1万年》。 拉锯多时的离岸人民币汇率USDCNH失守7.3关口&#xff0c;隔夜冲破7.36的高位。 为什么7.3是一个关键关口&#xff1f;因为这里是2022年10月底、11月初时曾经测试过的支撑位&#xff08;从CNH的角度说&#xff09;。 如果支撑位…

微信视频号挂公众号文章链接新方法:不限次数,不限号

当看到自己身边的人&#xff0c;通过我分享的方法绑定成功&#xff0c;那是开心到起飞了。 因为我知道&#xff1a;外面不靠谱的人很多&#xff01;分享不靠谱方法的人&#xff0c;可谓是更多。 为什么我要主动分享视频号评论区挂公众号文章链接&#xff1f;总有人伸张正义&a…

java中log使用总结

目录 一、概述1.1. 核心日志框架1.2 门面日志框架 二、最佳实践2.1 核心日志框架API包2.2 门面日志框架依赖2.3 集成使用2.3.1 集成jcl2.3.2 集成slf4j2.3.2.1 slf4j集成单一框架2.3.2.2 slf4j整合混合框架 三、总结3.1 所有相关包3.1.1 核心日志框架包3.1.2 门面日志框架3.1.3…

Python元类(metaclass)

Python 是一种强大的编程语言&#xff0c;一部分得益于其语言设计中独特的元类&#xff08;Metaclass&#xff09;机制。尽管元类的概念在刚开始接触时可能会让人感到困惑&#xff0c;但一旦理解了它们的工作原理和应用方式&#xff0c;我们就可以用它们做出强大且灵活的抽象。…

无涯教程-JavaScript - COUPDAYS函数

描述 COUPDAYS函数返回包含结算日期的息票期限内的天数。 语法 COUPDAYS (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证券的到…

Nginx重写功能

Nginx重写功能 一、Nginx常见模块二、访问路由location2.1location常用正则表达式2.2、location的分类2.3、location常用的匹配规则2.4、location优先级排列说明2.5、location示例2.6、location优先级总结2.7、实例2.7.1、location/{}与location/{}2.7.2、location/index.html{…

joplin更新后找不到文章

Joplin的数据默认是存储在C:\Users\Username.config\joplin-desktop下的。我修改为了D:\joplinnotes 这样就导致在升级覆盖安装的时候&#xff0c;笔记丢失路径。如果记不起之前笔记保存在哪里&#xff0c;也可以搜索类似文件来回忆之前自己保存笔记的位置 cache\ plugins\ re…

黑马JVM总结(三)

&#xff08;1&#xff09;栈内存溢出 方法的递归调用&#xff0c;没有设置正确的结束条件&#xff0c;栈会有用完的一天&#xff0c;导致栈内存溢出 可以修改栈的大小&#xff1a; 再次运行&#xff1a;减少了次数 案例二&#xff1a; 两个类的循环应用问题&#xff0c;导致Js…

注解生效激活(idea)

File---------settings-----------Build,Execution,Deployment-----------Compiler------- Annotation Processors

数据分析和可视化平台:Splunk Enterprise for mac v9.1.1激活版 兼容m1

Splunk Enterprise 是一个数据分析和可视化平台&#xff0c;可帮助企业理解其数据。虽然没有适用于 Mac OS 的 Splunk Enterprise 官方版本&#xff0c;但他们确实为 Mac OS 提供了一个名为“Splunk Light”的应用程序&#xff0c;它提供了基本的数据索引、搜索和仪表板。或者&…

「网页开发|前端开发|Vue」07 前后端分离:如何在Vue中请求外部数据

本文主要介绍两种在Vue中访问外部API获取数据的方式&#xff0c;通过让Vue通过项目外部的接口来获取数据&#xff0c;而不是直接由项目本身进行数据库交互&#xff0c;可以实现前端代码和后端代码的分离&#xff0c;让两个部分的代码编写更独立高效。 文章目录 本系列前文传送…

SpringMVC的常用注解,参数传递以及页面跳转的使用

目录 slf4j 常用注解 RequestMapping RequestParam RequestBody PathVariable 参数传递 首先在pom.xml配置文件中导入SLF4J的依赖 基础类型String 复杂类型 RequestParam PathVariable RequestBody 增删改查 返回值 void返回值 String返回值 modelString …

“高效记录收支明细,按时间轻松查找借款信息“

我们有时候要去查找借款信息&#xff0c;只记得住借款记录的日期&#xff0c;想通过日期来进行筛选出借款信息&#xff0c;要如何进行操作&#xff1f;今天就让小编来教教大家要如何操作。 第一步&#xff0c;我们要打开【晨曦记账本】&#xff0c;并登录账本。 第二步&#x…

弃用http改用https的缘故,与密钥的使用,证书意义

为何弃用http协议 在十几年前&#xff0c;我们的传输协议是http协议&#xff0c;为何到了如今改成了https协议呢&#xff1f;为了安全的考虑。 在http协议中&#xff0c;我们的内容是透明的&#xff0c;不被保护的&#xff0c;在黑客等恶意分子的面前&#xff0c;信息极其任意…

百度输入法全面升级,打造首个基于大模型的输入法原生应用

基于文心一言&#xff0c;百度输入法宣布全面升级&#xff0c;打造行业首个“基于大模型的输入法原生应用”&#xff0c;从“输入工具”全面转型为“AI创作工具”。 近日&#xff0c;百度文心一言正式向公众开放。基于文心一言&#xff0c;百度输入法宣布全面升级&#xff0c;打…

Spring Data Rest远程命令执行漏洞复现(CVE-2017-8046)

一、漏洞说明 Spring Data Rest服务器在处理PATCH请求时存在一个远程代码执行漏洞。攻击者通过构造好的JSON数据来执行任意Java代码 二、影响版本 Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3 Spring Boot version < 2.0.0M4 Spring Data release trains < K…

Python爬虫 教程:IP池的使用

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一、简介 爬虫中为什么需要使用代理 一些网站会有相应的反爬虫措施&#xff0c;例如很多网站会检测某一段时间某个IP的访问次数&#xff0c;如果访问频率…