Protocol Buffers(简称 protobuf)是一种由 Google 开发的数据序列化协议。它是一种与语言无关、平台无关、可扩展的机制,用于序列化结构化数据。你可以将其看作一种更小、更快、更简单的 XML 或 JSON 替代方案。
一、下载及安装
1.源码下载地址
https://github.com/protocolbuffers/protobuf/releases
2.下载完成后输入如下命令进行解压
tar zxvf protobuf-all-21.12.tar.gz
3.再输入如下命令进入工作目录
cd protobuf-21.12/
4.再然后运行如下命令生成makefile文件
./configure
5.我在输入上述命令后出错了,原因是 no acceptable C compiler found in $PATH,于是经过查阅资料后输入下列命令,再重新输入4目录,成功
sudo apt-get install build-essential
6.在成功生成makefile文件后,先输入make进行构建,在输入如下命令进行安装
sudo make install
7.安装完成后查看版本信息时出现如下错误,需要依次输入如下命令即可
sudo find / -name libprotoc.so.32
sudo vim /etc/ld.so.conf #将搜索到的路径加入该文件
sudo ldconfig
二、protobuf使用
在学习protbuf之前,我们需要搞清楚使用protbuf进行数据的序列化主要有哪几个步骤:确定数据格式,数据可简单可复杂,比如: struct Person { int id; string name; string sex; int age; }; 1.创建一个新的文件, 文件名随意指定, 文件后缀为 .proto
2.根据protobuf的语法, 编辑.proto文件
3.使用 protoc 命令将 .proto 文件转化为相应的 C++ 文件
4.需要将生成的c++文件添加到项目中, 通过文件中提供的类 API 实现数据的序列化/反序列化
1.编写cmakelists.txt文件
a.创建一个CMakeLists.txt文件,在该文件中先输入如下代码
cmake_minimum_required(VERSION 3.24) #cmake所要求最低版本
project(Protoc_test) #项目名称
set(CMAKE_CXX_STANDARD 17)#c++17
b.接下来搜索当前目录下所有的源文件
aux_source_directory(./ SRC)#./ 指在当前目录搜索 存入SRC变量中
c.添加静态库和链接protobuf的动态库
add_library(test ${SRC})
target_link_libraries(test protobuf)
2.编写.proto文件
将下列.c文件,编写转换为.proto文件
struct Person
{
int id;
int age;
string name;
};
syntax="proto3";
message Person{
int32 id=1;
int32 age=2;
bytes name=3;
}
执行如下命令,生成.pb.cc和.pb.h文件
protoc ./Person.proto –cpp_out=./
3.序列化
以下是四个序列化函数
bool SerializeToString(std::string* output) const; bool SerializeToArray(void* data, int size) const; bool SerializeToOstream(std::ostream* output) const; bool SerializeToFileDescriptor(int file_descriptor) const;
#include"Person.pb.h"
void test(){
//序列化
Person p;
p.set_id(10);
p.set_age(20);
p.set_name("zhu");
std::string s;
//序列化对象p
int Arr[1024];
p.SerializeToString(&s);//传出参数 s是二进制
//p.SerializeToArray(Arr,1024);第二种函数,将其存储至数组中
4.反序列化
以下是反序列化函数 bool ParseFromString(const std::string& data) ; bool ParseFromArray(const void* data, int size); bool ParseFromIstream(std::istream* input); bool ParseFromFileDescriptor(int file_descriptor);
//反序列化操作
Person pp;
pp.ParseFromString(s);//对其进行反序列化操作,谁调用这个函数,解析出来的数据就存储
//至哪个对象
std::cout<<pp.id()<<" "<<pp.age()<<" "<<pp.name();
}
int main(){
test();
}
三、protobuf中数据格式的转换
1.repeated
若数据成员中有数组,则给对应数据成员前加repeated;
repeated设置,如下
message responseCode{
uint32 errcode=1;
string errmsg=2;
}
message User{
bytes name=1;
uint32 age=2;
enum Sex{
man=0;
woman=1;
}
Sex sex=3;
}
message GerfrendsListsresponse{
responseCode code=1;
repeated User user=2;
}
使用:
GerfrendsListsresponse grsp;
User* user1=grsp.add_user();
user1->set_age(21);
user1->set_name("zhangsan");
user1->set_sex(User::Sex::User_Sex_man);
grsp.user_size();//list大小
User getuser=grsp.user(0);//传入下标获取user
responseCode* code=grsp.mutable_code();
code->set_errcode(1);
code->set_errmsg("error");
2.enum
enum若进行指定,第一个值必须为零
3.在proto文件中加入proto文件
在生成时需要也对xxx.proto进行生成
import "xxx.proto";
4.包(命名空间)
package 空间名;
在其他文件中使用
包名.类型
评论前必须登录!
注册