Protobuf3初步使用
一、Protobuf3
1.1 proto文件
文件基本结构示例如下。package
声明符的作用类似于C++
中的命名空间,防止不同.proto
间消息类型的命名冲突。message
是结构体,包含多个数据项field
,field
是一个key-value
类型。经过编译以后,message
生成对应的class
类,field
生成对应的方法。
syntax = "proto3";
package Example.Protobuf;
message Student
{
int32 no = 1;
string name = 2;
}
message School
{
Example.Protobuf.Student zhangsan = 1;
}
repeated
,用来表示字段可以重复任意次,可以用来表示数组、列表、映射等。如下map
示例:
syntax = "proto3";
package Example.Protobuf;
message Student
{
int32 no = 1;
string name = 2;
}
message MapStudentEntity
{
int32 key = 1;
Student studentVal = 2;
}
message School
{
repeated Example.Protobuf.MapStudentEntity mapStudentEntity = 1;
}
二、示例
2.1 生成C++接口文件
将1.1proto
文件命名为student.proto
,在该接口文件student.proto
所在目录,输入编译命令如下:
protoc student.proto --cpp_out=./
生成student.pb.cc
、student.pb.h
文件。
--cpp_out=OUT_DIR
:生成c++
头文件和源代码。
2.3 程序编写
编写C++
程序(Qt
),程序实现将自定义的结构体转为string
,再将string
转回结构体。过程中使用了protobuf
生成文件中的一些函数。
main.pro
如下:
QT += core
CONFIG += c++11
INCLUDEPATH += . $(E8000_ROOT)/inc
LIBS += -L$(PROTO_HOME)/lib -lprotobuf -lprotoc
HEADERS += \
student.pb.h \
struct.h
SOURCES += \
main.cpp \
student.pb.cc
与proto
文件中结构体对应的程序结构体定义在struct.h
中:
#pragma once
#include "student.pb.h"
#include <QMap>
struct Student
{
int nNo;
std::string sName;
Student()
{
nNo = 0;
sName = "";
}
public:
bool serializeToString(std::string& _strEncode) const;
bool parseFromString(const std::string& _strEncode);
};
inline bool Student::serializeToString(std::string& _strEncode) const
{
auto pStudent = std::make_shared<Example::Protobuf::Student>();
pStudent->set_no(Student::nNo);
pStudent->set_name(Student::sName);
bool bOk = pStudent->SerializeToString(&_strEncode);
return bOk;
}
inline bool Student::parseFromString(const std::string& _strEncode)
{
auto pStudent = std::make_shared<Example::Protobuf::Student>();
bool bOk = pStudent->ParseFromString(_strEncode);
if (bOk)
{
Student::nNo = pStudent->no();
Student::sName = pStudent->name();
}
return bOk;
}
struct School
{
QMap<int, Student> studentInfoMap;
public:
bool serializeToString(std::string& _strEncode) const;
bool parseFromString(const std::string& _strEncode);
};
inline bool School::serializeToString(std::string& _strEncode) const
{
auto pSchool = std::make_shared<Example::Protobuf::School>();
for (int nKey : School::studentInfoMap.keys())
{
Example::Protobuf::MapStudentEntity* pEntity = pSchool->add_mapstudententity();
pEntity->set_key(nKey);
Student student = School::studentInfoMap[nKey];
auto pStudent = std::make_shared<Example::Protobuf::Student>();
pStudent->set_no(student.nNo);
pStudent->set_name(student.sName);
pEntity->mutable_studentval()->CopyFrom(*pStudent);
}
bool bOk = pSchool->SerializeToString(&_strEncode);
return bOk;
}
inline bool School::parseFromString(const std::string& _strEncode)
{
auto pSchool = std::make_shared<Example::Protobuf::School>();
bool bOk = pSchool->ParseFromString(_strEncode);
if (bOk)
{
for (int i = 0; i < pSchool->mapstudententity_size(); i++)
{
Example::Protobuf::MapStudentEntity entity = pSchool->mapstudententity(i);
int nKey = entity.key();
Student student;
student.nNo = entity.studentval().no();
student.sName = entity.studentval().name();
School::studentInfoMap.insert(nKey, student);
}
}
return bOk;
}
测试程序(主程序)进行测试,将结构体转为string
,再把string
转为结构体。程序位于main.cpp
中。
#include "struct.h"
#include <QDebug>
using namespace std;
int main(int argc, char* argv[])
{
//结构体(protobuf)转string
Student s1, s2, s3;
s1.nNo = 1;
s1.sName = "liming";
s2.nNo = 2;
s2.sName = "lihong";
s3.nNo = 3;
s3.sName = "lifang";
School school1;
school1.studentInfoMap.insert(1, s1);
school1.studentInfoMap.insert(2, s2);
school1.studentInfoMap.insert(3, s3);
string sProto;
bool bOk = school1.serializeToString(sProto);
//string转结构体(protobuf)
School school2;
bOk = school2.parseFromString(sProto);
for (int nKey : school2.studentInfoMap.keys())
{
qDebug() << school2.studentInfoMap[nKey].nNo;
qDebug() << QString::fromStdString(school2.studentInfoMap[nKey].sName);
}
return 0;
}
输出结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?