【protobuf快速入门】

Protobuf 概述

  • protobuf也叫protocol buffer是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python 等,每一种实现都包含了相应语言的编译器以及库文件。
  • 由于它是一种二进制的格式,比使用 xml 、json进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
  • 此外相较于json和xml,protobuf还支持复杂的数据格式,如嵌套的结构体,树,图,等。

如何使用

step1

创建一个新的文件, 文件名随意指定, 文件后缀为 .proto根据protobuf的语法, 编辑.proto文件,

syntax="proto3";
message 名字	
{
    // 类中的成员, 格式
    数据类型 成员名字 = 1;
    数据类型 成员名字 = 2;
    数据类型 成员名字 = 3;
	   ......     
	   ......
}

根据我们想要的数据格式指定messge的格式,protobuf中的格式语法与c++结构体大致相同,这里我们假定编辑一个person的结构体

syntax = "proto3";
// 在该文件中对要序列化的结构体进行描述
message Person
{
    int32 id = 1;
    bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;
}

step2

.proto文件编辑好之后就可以使用protoc工具将其转换为C++文件了,执行之后就会得到xxx.pb.h,与xxx.pb.c

$ protoc -I path .proto文件 --cpp_out=输出路径(存储生成的c++文件)
  • protoc 命令中,-I 参数后面可以跟随一个或多个路径,用于告诉编译器在哪些路径下查找导入的文件或依赖的文件,使用绝对路径或相对路径都是没问题的。

step3

需要使用的地方的#include"xxx.pb.h"

序列化与反序列化

#include "MyTest.h"
#include "Person.pb.h"
void MyTest::test() {
    Person p;
    p.set_id(10);
    p.set_age(32);
    p.set_sex("man");
    p.set_name("lucy");
    std::string output;
    p.SerializeToString(&output);//序列化 并且output是二进制而不是字符串

    Person pp;
    pp.ParseFromString(output);//反序列化
    std::cout<<pp.id()<<","<<pp.sex()<<","<<pp.name()<<","<<pp.age()<<","<<std::endl;

}

messge中嵌套messge

与c++中结构体一样 写在一个文件中就行

message Address 
{
	int32 num=1;
	bytes addr = 2;
}
message Person
{
    int32 id = 1;
    bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;
    Address addr=5;
}

需要注意:在进行序列化时 person.addr是一个const值不可修改 这里需要使用mutable_addr(得到一个地址)

person.mutable_addr()->set_addr("武汉市")
person.mutable_addr()->set_num(1)

messge中嵌套数组

使用repeat关键字(动态数组)

message Person
{
    int32 id = 1;
    repeat bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;
    Address addr=5;
}

初始化

//方式一
person.add_name();//分配内存
person.set_name(index,value);
//方式二
person.add_name(value);

messge中嵌套枚举

与c++中枚举不同的是 第一个元素必须指定为0元素之间用隔开

// 定义枚举类型
enum Color
{
    Red = 0;
    Green = 3;		// 第一个元素以外的元素值可以随意指定
    Yellow = 6;
    Blue = 9;
}
// 在该文件中对要序列化的结构体进行描述
message Person
{
    int32 id = 1;
    repeated bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;   
    Color color = 5; // 枚举类型
}

初始化

person.set_color(Color::blue)

导入protoc文件

Address.proto

syntax = "proto3";
message Address 
{
	int32 num=1;
	bytes addr = 2;
}

Person.proto

syntax = "proto3";
import "Address.proto"
message Person
{
    int32 id = 1;
   	repeat bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;
    Address addr=5;
}

执行命令

因为有两个proto文件所以这里需要执行两个命令

 protoc Person.proto --cpp_out=./
 protoc Address.proto --cpp_out=./

同样也会得到两个文件 Person.pb.h 与 Address.pb.h 两个文件都有include到使用的文件

在C++中通过namespace来进行避免重名和分类,在protobuf中则是包(package)

proto文件 - Address.proto

syntax = "proto3";
// 添加命名空间 Dabing
package Dabing;
// 地址信息, 这个Address类属于命名空间: Dabing
message Address
{
    bytes addr = 1;
    bytes number = 2;
}

proto文件 - Person.proto

syntax = "proto3";
// 使用另外一个proto文件中的数类型, 需要导入这个文件
import "Address.proto";
// 指定命名空间 ErBing
package ErBing;

// 以下的类 Person 和枚举 Color 都属于命名空间 ErBing
// 在该文件中对要序列化的结构体进行描述
// 定义枚举类型
enum Color
{
    Red = 0;
    Green = 3;		// 第一个元素以外的元素值可以随意指定
    Yellow = 6;
    Blue = 9;
}
// 在该文件中对要序列化的结构体进行描述
message Person
{
    int32 id = 1;
    repeated bytes name = 2;
    bytes sex = 3;	
    int32 age = 4;
    // 枚举类型
    Color color = 5;
    // 添加地址信息, 使用的是外部proto文件中定义的数据类型
    // 如果这个外边类型属于某个命名空间, 语法格式:
    // 命名空间的名字.类名 变量名=编号;
    Dabing.Address addr = 6;
}

在c++中使用

//方式一
using namespace Dabing
using namespace Erbing
//方式二
Erbing::Person p;
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值