Protobuf 新手教程


Protobuf 是Google官方出品一種輕便高效的結構化數據存儲格式,可以用於結構化數據串行化,或者說是序列化。它很適合做數據存儲或RPC數據交換格式。可用於通訊協議、數據存儲等領域的平台無關、語言無關、可擴展的序列化結構數據格式。

優點

  • 平台無關,語言無關,可擴展

  • 提供了友好的動態庫,使用簡單

  • 解析速度快,比對應的XML快約20-100倍

  • 序列化數據非常簡潔、緊湊,與XML相比,其序列化之后的數據量約為1/3到1/10

缺點

protobuf對於1M以下的message有很高的效率,但是當message是大於1M的大塊數據時,protobuf的表現不是很好,請合理使用。

Proto文件

使用 protobuf, 需要先書寫 .proto 文件,然后編譯該文件。編譯 proto 文件則需要使用官方的 protoc 工具。

// Filename: addressbook.proto

syntax="proto2";  // 表明使用protobuf的編譯器版本為v2,目前最新的版本為v3   
package addressbook;

message Person {    //message是Protobuf中的結構化數據,類似於C++中的類,可以在其中定義需要處理的數據
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message PhoneNumber {
        required string number = 1;
        optional PhoneType type = 2 [default = HOME];
    }

    repeated PhoneNumber phone = 4;
}

message AddressBook {
    repeated Person person_info = 1;
}

/*

1,2,3 是字段的標識號,在消息定義中,每個字段都有唯一的一個數字標識號,這些標識號是用來在消息的二進制格式中識別各個字段的,一旦開始使用就不能夠再改變。
標識號的范圍在:1 ~ 229 - 1,其中[19000-19999]為Protobuf預留,不能使用。

Person 內部聲明了一個enum和一個message,這類似於C++中的類內聲明,Person外部的結構可以用 Person.PhoneType 的方式來使用PhoneType。當使用外部package中的結構時,要使用 pkgName.msgName.typeName 的格式,每兩層之間使用'.'來連接,類似C++中的"::"。

*/

標量類型列表

proto類型 C++類型 備注
double double  
float float  
int32 int32 使用可變長編碼,編碼負數時不夠高效——如果字段可能含有負數,請使用sint32
int64 int64 使用可變長編碼,編碼負數時不夠高效——如果字段可能含有負數,請使用sint64
uint32 uint32 使用可變長編碼
uint64 uint64 使用可變長編碼
sint32 int32 使用可變長編碼,有符號的整型值,編碼時比通常的int32高效
sint64 int64 使用可變長編碼,有符號的整型值,編碼時比通常的int64高效
fixed32 uint32 總是4個字節,如果數值總是比總是比228大的話,這個類型會比uint32高效
fixed64 uint64 總是8個字節,如果數值總是比總是比256大的話,這個類型會比uint64高效
sfixed32 int32 總是4個字節
sfixed64 int64 總是8個字節
bool bool  
string string 一個字符串必須是UTF-8編碼或者7-bit ASCII編碼的文本
bytes string 可能包含任意順序的字節數據


 

 win10系統下,C++開發如何使用

1、源碼安裝

訪問最新地址,c++ 開發則下載 protobuf-cpp-3.19.1.tar.gz; 或是 protoc-3.19.1-win64.zip

https//github.com/protocolbuffers/protobuf/release/latest

2、解壓源碼到任意路徑下

path/protobuf-3.19.1

3、下載 CMake 工具

4、CMake生成 VS2019 工程

  • 打開CMake

  • 設置源碼路徑下的cmake目錄 path/protobuf-3.19.1/cmake

  • 設置任意構建目錄 path/protobuf_build

  • 點擊 configure、選擇對應 VS,編譯為 WINI32,編譯器默認

  • 點擊Finish按鈕,開始自動編譯

  • 點擊 Generate 生成VS項目

  • 用 VS 打開生成的工程,按需要選擇編譯 libprotobuf、libprotobuf-lite、libprotoc和protoc項目

  • 在 release 或者 debug目錄,找到 lib 文件和 protoc.exe

5、protoc.exe 使用命令行將 .proto 文件編譯生成對應的 .h 和 .cc 文件

# 標准命令
protoc -I=./ --cpp_out=./ ./test.proto
#--cpp_out 是輸出路徑,  ./為當前路徑

6、引入自己的 VS2019 工程使用

  • 拷貝 *.pb.cc 和 *.pb.h 文件到當前項目

  • 拷貝 src目錄下的goole文件夾到當前項目的include目錄下

  • 拷貝 libprotobuf.lib libprotoc.lib 到當前項目的 lib 目錄下

  • 項目設置為多字節,添加靜態鏈接庫

  • C/C++ General Additional Include Directories 添加include目錄

  • Linker General Additional Library Directories 添加 lib 目錄

  • Linker Input Additional Dependencies 添加 lib 字段名

7、VS編譯或是g++編譯生成可執行代碼

g++ main.cc xxx.pb.cc -I $INCLUDE_PATH -L $LIB_PATH -lprotobuf -pthread

 

常用API

protoc 為message的每個required字段和optional字段都定義了一下幾個函數,不限於這幾個

TypeName xxx() const;           //獲取字段
// bool has_xxx();              //判斷是否設置值   pb 2
void set_xxx(const TypeName&);  //設置
void clear_xxx();               //使其變為默認值

為每個 repeated 字段定義了以下幾個:

TypeName* add_xxx();            //增加結點
TypeName xxx(int) const;        //獲取指定序號的結點,類似於c++的“[]”運算符
TypeName* mutable_xxx(int);     //類似於上一個,但是獲取的是指針
int xxx_size();                 //獲取結點的數量

幾個常用的序列化函數

bool SerializeToOstream(std::ostream * output) const;   //輸出到輸出流中
bool SerializeToString(string * output) const;          //輸出到string
bool SerializeToArray(void * data, int size) const;     //輸出到字節流

與之對應的反序列化函數

bool ParseFromIstream(std::istream * input);            //從輸入流解析
bool ParseFromString(const string & data);              //從string解析
bool ParseFromArray(const void * data, int size);        //從字節流解析

其他常用函數

bool IsInitialized();       // 檢查是否所有required字段都被設值
size_t ByteSize() const;    // 獲取二進制字節序的大小    pb2
官方API文檔: https://developers.google.com/protocol-buffers/docs/reference/overview

參考資料

https://www.cnblogs.com/autyinjing/p/6495103.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM