Protobuf3初步使用

一、Protobuf3

1.1 proto文件

​ 文件基本结构示例如下。package声明符的作用类似于C++中的命名空间,防止不同.proto间消息类型的命名冲突。message是结构体,包含多个数据项fieldfield是一个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.ccstudent.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;
}

​ 输出结果:

posted @   一方之水  阅读(139)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示