最近在折腾项目的时候碰到了这个知识点,查了不少资料,索性整理出来分享给大家。
目录
3.1.定义 Protobuf 数据结构(.proto 文件)
1.简介
Protocol Buffers(简称 Protobuf) —— Google 开发的一种语言无关、平台无关、可扩展的结构化数据序列化协议。相比 JSON/XML,它体积更小、速度更快、兼容性更强,是微服务、网络通信、数据存储的首选序列化方案。
特点有:
- 高效:二进制序列化,体积比 JSON 小 3-10 倍,速度快 20-100 倍;
- 强类型:编译期检查数据类型,避免运行时错误;
- 兼容:向后 / 向前兼容,新增字段不影响旧代码;
- 跨语言:一套
.proto定义,生成 C++/Java/Python/Go 等代码;非常适合多语言微服务架构。
2.安装
2.1.快速安装
系统安装命令Ubuntu/Debiansudo apt install protobuf-compiler libprotobuf-devmacOSbrew install protobufWindowsvcpkg install protobuf protobuf:x64-windows
验证安装:
protoc --version # 查看编译器版本,成功输出则安装完成
2.2.源码编译安装
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git checkout v3.21.12 # 选择稳定版本
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
3.C++中使用流程
3.1.定义 Protobuf 数据结构(.proto 文件)
创建 person.proto,这是 Protobuf 的接口定义文件,所有数据结构都在这里声明(推荐使用 proto3 语法,更简洁):
// 指定语法版本(必须写在第一行)
syntax = "proto3";
// 生成的 C++ 代码命名空间
package tutorial;
// 定义消息体(对应 C++ 类)
message Person {
// 字段规则:字段类型 字段名 字段编号(必须唯一)
string name = 1; // 姓名
int32 age = 2; // 年龄
string email = 3; // 邮箱
// 嵌套枚举类型
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
// 嵌套消息类型
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
// 重复字段(对应 C++ 容器,存储多个手机号)
repeated PhoneNumber phones = 4;
}
关键语法说明:
- 字段编号 :每个字段后的
= 1、= 2是唯一的字段标识符,一旦定义就不能更改,这是向后兼容性的关键。 - 字段规则:
singular (默认):0 或 1 个值
repeated:0 或多个值(类似 C++ 的vector)optional(proto2 或 proto3 2023+):可选字段required(仅 proto2):务必字段
:int32、int64、uint32、uint64、sint32、sint64、fixed32、fixed64、sfixed32、sfixed64、float、double、bool、string、bytes、枚举、其他消息类型。
3.2.编译生成 C++ 代码
使用 protoc 编译器将 .proto 文件编译为 C++ 头文件和源文件:
# --cpp_out=. :生成 C++ 代码到当前目录
protoc --cpp_out=. person.proto
执行后会生成两个文件:
person.pb.h:头文件(声明类、方法)person.pb.cc:源文件(实现序列化 / 反序列化)
3.3.编写 C++ 业务代码
创建 main.cpp,实现对象赋值、序列化、反序列化核心逻辑:
```
include
include
include
// 引入Protobuf生成的头文件
include "person.pb.h"
// 序列化:Person对象 → 二进制字符串
void Serialize(const tutorial::Person& person, std::string& data) {
person.SerializeToString(&data);
}
// 反序列化:二进制字符串 → Person对象
void Deserialize(tutorial::Person& person, const std::string& data) {
person.ParseFromString(data);
}
int main() {
// 1. 初始化Protobuf(务必调用,全局仅一次)
GOOGLE_PROTOBUF_VERIFY_VERSION;
// ========== 2. 构造Person对象 ==========
tutorial::Person person;
person.set_name("张三");
person.set_age(25);
person.set_email("zhangsan@test.com");
// 添加重复字段(手机号)
auto phone1 = person.add_phones();
phone1->set_number("13800138000");
phone1->set_type(tutorial::Person::MOBILE);
auto phone2 = person.add_phones();
phone2->set_number("010-12345678");
phone2->set_type(tutorial::Person::HOME);
// ========== 3. 序列化 ==========
std::string serialized_data;
Serialize(person, serialized_data);
std::cout
暂时整理到这里。以上都是个人理解,可能有疏漏,欢迎指正。
评论 (0)
暂无评论