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

pb生成文件和反射

1.protoc生成文件

指定生成的目录和proto文件路径,

protoc --cpp_out=./ ./echo.proto
// echo.proto
syntax = "proto3";package echo;option cc_generic_services = true;message EchoRequest {string msg = 1;
}message EchoResponse {string msg = 2;
}service EchoService {rpc Echo(EchoRequest) returns (EchoResponse);
}

使用 protoc 命令编译 .proto 文件时,会生成两个主要的 C++ 文件:

  1. echo.pb.h(头文件)
  2. echo.pb.cc(源文件)

1.1 pb头文件

echo.pb.h 是 Protocol Buffers 自动生成的头文件,主要用于声明消息(message类型)的类、方法、枚举以及相关的类型信息,还有服务类(Service类)。它的内容包含以下几个部分:

  • 类声明:为每个 .proto 文件中的消息定义一个对应的 C++ 类。例如,如果你在 .proto 文件中定义了一个 Message 类型,头文件中会生成一个 Message 类。

  • 字段的访问器和修改器方法:每个消息类中的字段都会有 getter 和 setter 函数。这些函数用于访问和修改 Protocol Buffers 消息中的字段。例如,set_field()field()clear_field() 等函数。

  • // 序列化和反序列化函数:包含用于将消息对象序列化为二进制格式或从二进制格式反序列化的函数。常见的方法包括 SerializeToString()ParseFromString()。// 这个实际不在生成的文件中。

  • 其他辅助函数:如比较函数(operator==),清理函数(Clear()),以及元数据函数(例如 descriptor())。

服务类类型:

服务类 EchoService 是一个抽象类,声明了服务器端和客户端接口,具体如下:

  • 服务端接口:EchoService::Echo() 是一个虚函数,必须在服务器端的实现类中进行具体的定义。服务器端代码需要继承这个类并实现其中的 Echo() 方法。
class EchoService : public ::grpc::Service {public:virtual ~EchoService();// Abstract method to be implemented on the server sidevirtual ::grpc::Status Echo(::grpc::ServerContext* context,const EchoRequest* request,EchoResponse* response) = 0;// Method to register the service with a gRPC server::grpc::ServerUnaryCallHandlerFactoryBase<EchoRequest, EchoResponse>* RegisterEcho();// Other methods for service registration and reflection
};

服务器端实现:服务器端需要继承 EchoService 类并实现 Echo() 方法。例如:

class MyEchoServiceImpl : public EchoService {::grpc::Status Echo(::grpc::ServerContext* context, const EchoRequest* request, EchoResponse* response) override {// Implement your logic hereresponse->set_msg("Response to: " + request->msg());return ::grpc::Status::OK;}
};
  • 客户端接口Stub 是客户端调用远程 RPC 服务的接口,声明如下。客户端代码通过 Stub 调用 Echo() 方法进行远程调用,发送请求并接收响应。
class EchoService::Stub : public ::grpc::Client {public:// Method to invoke the RPC from the client::grpc::Status Echo(::grpc::ClientContext* context, const EchoRequest& request, EchoResponse* response);
};

1.2 pb源文件

echo.pb.cc 是 Protocol Buffers 自动生成的源文件,主要包含消息类方法的实现。它是 echo.pb.h 中声明的方法的具体定义。源文件的内容主要包括:

  • 构造函数和析构函数:消息类的构造函数、析构函数,以及复制构造函数等。

  • 字段访问器和修改器的实现:具体实现 pb.h 文件中声明的 getter 和 setter 函数,用于访问和修改pb 消息中的字段。

  • 序列化和反序列化的实现:具体实现序列化和反序列化的方法,例如 SerializeToArray()ParseFromArray() 等。

  • 字段的内存管理:管理动态分配的内存(如果消息包含嵌套消息或 repeated 字段)。

  • 消息的元数据:通常包含与消息相关的反射信息,用于支持 Protocol Buffers 的动态功能(如反射系统,descriptor 元数据等)。

2.pb反射机制

Protocol Buffers 的反射机制允许你在运行时动态地操作消息对象,而无需在编译时明确知道其类型或字段。// 可以认为能获取到元数据的机制就是反射机制。

反射使得开发者可以在运行时通过一种通用的方式来操纵 Protocol Buffers 消息,包括:

  1. 获取消息的元数据(如字段的名称、类型等)。
  2. 动态访问和修改消息的字段,即使这些字段在编译时是未知的。
  3. 遍历所有的字段,包括已设置的和未设置的字段。
  4. 动态序列化和反序列化消息,无需依赖具体的消息类型。

反射机制特别适合以下场景:

  • 通用工具或框架:如调试器、序列化框架、消息检查工具等,使用反射可以处理多种不同的消息类型。
  • 不确定消息类型的情况下:如当消息的类型在运行时才能确定时(例如在 RPC 系统中使用动态消息分发)。
const google::protobuf::Descriptor* descriptor = echo::EchoRequest::descriptor();
std::cout << descriptor->name();  // 打印消息名称
  • 在这个例子中,descriptor() 方法返回的是 EchoRequest 消息的描述符,通过它可以获取消息的名称、字段的数量等信息。
echo::EchoRequest req;
req.set_msg("Hello, World!");// 返回反射对象
const google::protobuf::Reflection* reflection = req.GetReflection();
// 通过字段名称获取 FieldDescriptor
const google::protobuf::FieldDescriptor* field = req.descriptor()->FindFieldByName("msg");// 通过反射获取字段的值
std::string value = reflection->GetString(req, field);
std::cout << "msg field value: " << value << std::endl;

反射对象通过描述符与消息的实际实例交互。通过反射对象,你可以在运行时获取和设置消息字段的值,而不需要直接访问消息对象的成员函数

其他常用的反射操作:

// 获取字段值
int32_t id_value = reflection->GetInt32(message, field_descriptor);// 设置字段值
reflection->SetString(&message, field_descriptor, "New Value");// 检查字段是否已设置
if (reflection->HasField(message, field_descriptor)) {// 字段已设置
}// 清除字段
reflection->ClearField(&message, field_descriptor);

// 看起来还是要知道字段名和类型。

2.1 动态消息遍历

const google::protobuf::Descriptor* descriptor = req.descriptor();
const google::protobuf::Reflection* reflection = req.GetReflection();for (int i = 0; i < descriptor->field_count(); ++i) {const google::protobuf::FieldDescriptor* field = descriptor->field(i);if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {std::string value = reflection->GetString(req, field);std::cout << field->name() << ": " << value << std::endl;}
}

使用 field_count() 获取消息的字段总数,然后遍历每个字段,检查字段类型并获取其值。

// 但感觉这里有点怪怪的,reflection指针是从req返回的,但是reflection调用自己成员函数的时候还要把req传进去。

相关文章:

pb生成文件和反射

1.protoc生成文件 指定生成的目录和proto文件路径&#xff0c; protoc --cpp_out./ ./echo.proto // echo.proto syntax "proto3";package echo;option cc_generic_services true;message EchoRequest {string msg 1; }message EchoResponse {string msg 2; }…...

.net framework 3.5sp1安装错误卡住不动怎么解决

解决 .NET Framework 3.5 SP1 安装错误卡住的问题&#xff0c;可以尝试以下几种方法&#xff1a; 1.使用 DISM 工具&#xff1a; 将下载的 NetFx3.cab 文件放置在 C:\Windows 文件夹下。 以管理员身份打开命令提示符&#xff0c;输入以下命令&#xff1a; dism /online /En…...

毕业设计—基于 Inception-ResNet模型的皮肤癌分类系统实现

1.摘要 皮肤癌是人类最常见的恶性肿瘤&#xff0c;主要通过视觉诊断进行初步临床筛查。但是由于皮肤病变外观的细微变化性&#xff0c;使用图像自动分类皮肤病变是一项具有挑战性的任务。本文为了提高深度学习算法在皮肤病检测上的准确率&#xff0c;本文提出了基于Inception和…...

什么是优秀的单元测试?

阅读本文之前&#xff0c;请投票支持这款 全新设计的脚手架 &#xff0c;让 Java 再次伟大&#xff01; 单元测试的质量意义 合理编写单元测试&#xff0c;可使团队工程师告别牛仔式编程&#xff0c;产出易维护的高质量代码。随着单元测试覆盖率的上升&#xff0c;项目会更加…...

服务器安装Anaconda,Anaconda安装Pytorch

1.服务器安装Anaconda 1.1 下载Anaconda 在服务器上直接下载 wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh1.2 安装Anaconda bash Anaconda3-2024.06-1-Linux-x86_64.sh然后就显示下面&#xff1a;more 安装过程一直enter即可&#xff0c;…...

YOLO目标检测理论详解,YOLOv1理论知识讲解,超w字精读(学习YOLO框架必备),全网最详细教程

文章目录 前言一、目标检测理论1.目标检测发展史2.目标检测框架理论基础3.本章小结 二、YOLOv1理论知识1.YOLOv1网络结构2.YOLOv1检测原理3.YOLOv1的训练流程&#xff08;1&#xff09;边界框的位置参数&#xff08;2&#xff09;边界框的置信度&#xff08;3&#xff09;类别置…...

SpringBoot3.x和OCR构建车牌识别系统

本专题旨在展示 OCR 技术与 SpringBoot3.x 框架结合的广泛应用。我们会深入探讨它在医疗、金融、教育、交通、零售、公安等多个领域的现实应用。每个应用场景都会提供详细的实例、面临问题的分析与解决策略&#xff0c;以帮助您深入理解 OCR 技术在实践中的关键作用。让我们一同…...

conda 容器学习笔记之一 -- 基础环境配置

1、容器瘦身导致部分应用缺少&#xff0c;需要在非容器环境下部署环境。但为避免破坏现有环境&#xff0c;现有使用conda环境进行隔离管理 创建&#xff1a;conda create -n tts python3.10.0 2、conda 是python环境管理&#xff0c;和python无关的东西比如cann还是会影响 下载…...

Oracle分区表改造(三):通过分区交换和分裂改造为分区表

Oracle分区表改造(三):通过分区交换和分裂改造为分区表 源表数据准备范围分区表改造:非间隔分区创建普通分区表分区交换分区分裂范围分区表改造:间隔分区创建间隔分区表分区交换分区分裂表重命名🐬 创建只有一个分区的分区表, 通过分区交换将原表变成分区表,然后分裂分…...

LeetCode 0908.最小差值 I:思维(遍历)

【LetMeFly】908.最小差值 I&#xff1a;思维&#xff08;遍历&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/smallest-range-i/ 给你一个整数数组 nums&#xff0c;和一个整数 k 。 在一个操作中&#xff0c;您可以选择 0 < i < nums.length 的…...

Python基础之循环语句

在Python的编程世界里&#xff0c;循环结构犹如一把神奇的钥匙&#xff0c;开启高效处理数据和重复执行任务的大门。它赋予程序员强大的力量&#xff0c;让代码充满活力。Python主要有两种类型的循环语句&#xff1a;for循环和while循环。 一、for循环 for循环通常用于遍历一个…...

项目管理软件真的能让敏捷开发变得更简单吗?

敏捷开发是一种以快速交付和适应变化为核心特点的软件开发方法。其特点包括尽早并持续交付、能够驾驭需求变化、版本周期内尽量不加任务、业务与开发协同工作、以人为核心、团队配置敏捷等。 例如&#xff0c;尽早并持续交付可使用的软件&#xff0c;使客户能够更早地体验产品…...

互联网名称之时间戳

什么是时间戳 时间戳&#xff08;Timestamp&#xff09;是一种用于表示特定时刻的数值或字符串&#xff0c;通常以日期和时间的形式出现。它用于记录某一事件发生的准确时间&#xff0c;在计算机系统中常被用于日志记录、数据处理和同步等场景。 常见的时间戳 在互联网中常见…...

Leetcode—1242. 多线程网页爬虫【中等】Plus(多线程)

2024每日刷题&#xff08;187&#xff09; Leetcode—1242. 多线程网页爬虫 实现代码 /*** // This is the HtmlParsers API interface.* // You should not implement it, or speculate about its implementation* class HtmlParser {* public:* vector<string>…...

RISC-V笔记——内存模型总结

1 前言 Memory consistency model定义了使用Shared memory(共享内存)执行多线程(Multithread)程序所允许的行为规范。RISC-V使用的内存模型是RVWMO(RISC-V Weak Memory Ordering)&#xff0c;RVWMO内存模型是根据全局内存顺序(global memory order)定义的&#xff0c;全局内存…...

后端常用安全措施

一、限流 1.简介 限流就是限制流量&#xff0c;但这里的流量是一个比较笼统的概念。如果考虑各种不同的场景&#xff0c;限流是非常复杂的&#xff0c;而且和具体的业务规则密切相关 通过限流&#xff0c;可以控制服务请求的速率&#xff0c;从而提高系统应对突发大流量的能…...

虚拟机数据恢复—通过拼接数据库页碎片的方式恢复数据库的数据恢复案例

虚拟机数据恢复环境&#xff1a; 某品牌服务器通过同品牌某型号的RAID卡&#xff0c;将4块STAT硬盘为一组RAID10阵列。上层部署XenServer虚拟化平台&#xff0c;虚拟机安装Windows Server系统&#xff0c;每台虚拟机有两个虚拟机磁盘&#xff08;系统盘 数据盘&#xff09;&am…...

【vue】自封组件,基于vue2封装一个弹框组件

源码&#xff1a;https://download.csdn.net/download/galaxyJING/89913551...

ES6基础知识

一、定义变量的关键字let和const 1. let 定义变量的语法&#xff1a; let 变量名 值; 2. 和var定义变量的区别 1. 是否支持同一个作用域变量同名 var支持&#xff0c;let不支持 2. 是否支持预解析 var支持&#xff0c;let不支持 3. 是否会挂载在window对象…...

基于Multisim的模拟拔河游戏比赛设计与仿真

1.设计一个模拟拔河游戏比赛的逻辑电路 2.使用15个发光二极管表示绳子&#xff0c;开机后只有最中间的发光二极管亮。 3.比赛双方各持一个按钮&#xff0c;快速不断地按动按钮&#xff0c;产生脉冲&#xff0c;谁按的快&#xff0c;发光的二极管就向谁的方向移动&#xff0c;每…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...