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;
    }
    

    作者:溟洵

    物联沃分享整理
    物联沃-IOTWORD物联网 » 快速认识和上手Protobuf

    发表回复