快速认识和上手Protobuf

Protobuf

ProtoBuf(全称Protocol Buffer)是数据结构序列化和反序列化框架(谷歌开发)
它具有以下特点:

  • 语⾔⽆关、平台⽆关:即 ProtoBuf ⽀持 Java、C++、Python 等多种语⾔,⽀持多个平台
  • ⾼效:即⽐ XML (数据交换格式)更⼩、更快、更为简单
  • 扩展性、兼容性好:你可以更新数据结构,⽽不影响和破坏原有的旧程序(根据我们的需要自己生成需要的结构)

使用方法

  1. 编写的.proto文件,自定义结构对象及属性内容(描述对象中,有什么样的成员,每个成员具有什么样的属性。比如描述学生结构:姓名:字符串、学号:长整形、。。。)
  2. 编译proto文件:使用protoc编译器编译.proto文件中的描述,生成对应的接口代码,存放在新生成头文件和源文件中。
    1. .h 中定义了我们所描述的数据结构对象类;
    2. .cc定义实现了结构化对象的访问&操作&序列化&反序列化
  3. 使用:引入生成的头文件,在代码中根据需要使用即可。依赖⽣成的接⼝,将编译⽣成的头⽂件包含进我们的代码中,实现对. proto ⽂件中定义的字段进⾏设置和获取,和对 message 对象进⾏序列化和反序列化

编写的.proto文件

.proto文件规范:

  1. 创建.proto⽂件时,⽂件命名应该使⽤全⼩写字⺟命名 ,多个字⺟之间⽤_ 连接。例如:lower_snake_case.proto
  2. 书写.proto⽂件代码时,应使⽤2个空格的缩进(推荐而已不强制)

语法规则:

必须写:

1. 指定proto3语法(声明语法版本):
syntax = "proto3";
2. package声明符(声明命名空名称):
相当于命名空间,避免我们定义的消息出现冲突
package 根据情况命名 package contacts;
3. 定义结构化对象描述(定义结构化对象描述)
可以理解为类

message 消息类型名{
	各个字段描述: 字段类型 字段名 = 字段唯一编号;
}
例:
message contact{
	uint64 sn = 1;//学号
	string name = 2;//姓名
	float score = 3;//成绩
}

其中Protobuf的类型太多了就一一列出来了,建议有需求就直接搜。

编译contacts.proto文件

编译命令行格式为:

protoc  [--proto_path=IMPORT_PATH]  --cpp_out=DST_DIR  path/to/file.proto

1. protoc 是 Protocol Buffer 提供的命令⾏编译⼯具。
2. --proto_path 指定 被编译的.proto⽂件所在⽬录,可多次指定。可简写成 -IIMPORT_PATH 。如不指定该参数,则在当前⽬录进⾏搜索。当某个.proto ⽂件 import 其他.proto ⽂件时,或需要编译的 .proto ⽂件不在当前⽬录下,这时就要⽤-I来指定搜索⽬录。
3. --cpp_out= 指编译后的⽂件为 C++ ⽂件。
4. OUT_DIR 编译后⽣成⽂件的⽬标路径。
5. path/to/file.proto 要编译的.proto⽂件
6. [ ] 表示可以不写

例如生成c++的方法:
protoc --cpp_out=.  contacts.proto

实操 protoc编译.proto文件(附图 也可以直接看这快速了解):

  1. 编写.proto文件:
//声明proto语法版本
syntax = "proto3";
package contacts;

message Contact{
    uint64 sn = 1;
    string name = 2;
    float score = 3;
}

在这里插入图片描述
2. 编译.proto文件

protoc --cpp_out=. contacts.proto
1. protoc必备
2. --cpp_out:表示生成c++文件
3. ‘.’:表示生成的路径(当前路径) 
4. contacts.proto 要编写的proto文件)`

输出后就会生成两个文件:
在这里插入图片描述

了解生成的代码

常用接口(序列化、反序列化):

成员的get获取接口和set设置接口:
在这里插入图片描述

常用接口:

class MessageLite {
public:
//序列化:
bool SerializeToOstream(ostream* output) const; // 将序列化后数据写⼊⽂件流
bool SerializeToArray(void *data, int size) const;
bool SerializeToString(string* output) const;

//反序列化:
bool ParseFromIstream(istream* input); // 从流中读取数据,再进⾏反序列化动作
bool ParseFromArray(const void* data, int size);
bool ParseFromString(const string& data);
};

实操使用生成的文件:

  1. 创建contact类对象 conn

    1. 设置学号、姓名、成绩
  2. 序列化string str(存起来的是二进制的!)
    通过conn对象的SerializeAsString函数序列化的数据

  3. 反序列化获取数据在contact stu对象中:
    使用ParseFromString反序列化返回bool值

    1. 判断失败—返回-1
    2. 成功—打印存在的 stu 的成员对象
  4. 创建makefile

    1. g++编译(略)
    2. 注意需要连接protobuf库(-l连接外部库)-lprotobuf
#include <iostream>

#include "contacts.pb.h"
#include "contacts.pb.cc"
int main()
{
    contacts::contact conn;
    conn.set_sn(251);
    conn.set_name("坤坤");
    conn.set_score(91);

    std::string str = conn.SerializeAsString();

    contacts::contact stu;
    int n = stu.ParseFromString(str);
    if(n == -1){
        std::cout << "获取失败"<<std::endl;
    }
    else{
        std::cout << stu.sn() << std::endl;
        std::cout << stu.name() << std::endl;
        std::cout << stu.score() << std::endl;
    }

    return 0;
}

在这里插入图片描述

上一篇:手机ip地址异常怎么解决


下一篇:STM32学习笔记----RTC的功能及其使用