protobuf

編譯安裝

        http://www.cnblogs.com/javaee6/p/4849051.htmlhtml

使用

其實用法很是簡單(暫時沒有涉及到tcp的封包等問題):java

1 proto文件的語法

主要的模板以下:c++

package tutorial; 這個包名會成爲一個名字空間

message Person {
    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 = 1;
}

以上的proto文件用protoc命令生成一個.h文件和一個.cc文件,這兩個文件就是生成的類的定義。數組

注意:tcp

required 規定必須提供字段,不然message就是沒有初始化的。ui

optional 能夠設置,也能夠不設置字段。不設置字段時會使用默認值,能夠指定可選字段的默認值。spa

     若是沒有指定默認值,則對於數值類型,0是默認值;設計

     對於字符串,空字符串是默認值;指針

     對於bool類型,false是默認值;調試

     對於嵌入的message類型,默認值是此message的默認實例或者元類型,其中每一個字段都沒有設置。

     對於沒有顯示設定值的可選或者必選字段,調用訪問器老是返回字段的默認值。

repeated 定義字段能夠重複屢次(包括0次)。各個重複的值的次序會保留,能夠把重複字段看做是動態數組。

 

protoc -I=./ --cpp_out=./ XXXXXXXXXXXX.proto
其中-I指定的是proto文件所在的路徑,--cpp_out是指定生成的c++類定義文件的路徑,最後那個.proto指定的是具體的編寫的proto文件的名稱。

2 生成的類的定義與接口詳解

每一個mesage的生成的類定義會有以下的特性:

2.1 訪問器方法(geter和seter):

1 訪問器方法:
get方法就是字段的名稱
set方法是set_後面加上字段的名稱
如:
set方法:
inline void set_email(const std::string& value);
inline void set_email(const char* value);
get方法:
inline const ::std::string& email() const;

2 has_方法: 用來判斷是否爲(可選或者必選)字段設置過值
如:
inline bool has_email() const;

3 clear_方法: 清除字段值,使之成爲空狀態
如:
inline void clear_email();

4 字符串:多了mutable_方法,能夠取得字段值的間接指針;還多了一個set_方法,是用char指針做爲參數。
5 repeated字段,會有以下的方法:
A _size方法:判斷有多少個元素
如:
inline int phone_size() const;

B 沒有has_方法

C 經過索引取得或者更新元素
如:
inline const ::tutorial::Person_PhoneNumber& phone(int index) const;

D add_方法:加入新的元素
如:
inline ::tutorial::Person_PhoneNumber* add_phone();

2.2 枚舉和嵌套類型

生成的代碼含有枚舉類型Person::PhoneType,其值能夠是Person::MOBILE、Person::HOME、Person::WORK
生成的代碼含有嵌套類Person::PhoneNumber,可是實際的名稱是Person_PhoneNumber,若是須要前向聲明,則須要使用名字Person_PhoneNumber。

2.3 標準消息方法

bool IsInitialized() const:是否全部必需的字段都已經設置
string DebugString() const:返回表示消息的人類可讀的字符串,對於調試特別有用
void CopyFrom(const Person& from):複製
 void Clear():清除全部字段

2.4 解析和序列化

A bool SerializeToString(string* output) const;
序列化message,存儲到string中。注意其中的字節是二進制的,而不是文本。也就是說序列化以後,如寫入文件等,你仍然看不懂,由於是二進制的。

B bool ParseFromString(const string& data);
從字符串中解析出message,這就是反序列化。

C bool SerializeToOstream(ostream* output) const;
將消息寫入到C++ ostream中。

D bool ParseFromIstream(istream* input);
從C++ istream中解析出消息。

以上也就是說,protocol buffer總共有那麼兩種類型的交互方式:一種就是直接跟string進行交互;還有一種就是跟istrem或者ostream進行交互。

3 可擴展性設計原則

應用發佈以後,未來極可能須要改進protocol buffer定義。爲保證新的格式向後兼容,舊的格式向前兼容,對於新版本的定義:
· 不得修改任何已有字段的序號
· 不得增長或者刪除required字段
· 能夠刪除optional或者repeated字段
· 能夠添加新的optional或者repeated字段,可是必須使用新的序號
   只要遵循上述規則,則舊的程序能夠很好地處理新的消息(簡單地忽略新的字段)。
· 對於舊的程序:被刪除的optional字段具備默認值;被刪除的repeated字段是空的。新的程序也能夠透明地處理舊的消息。
· 可是:新的optional字段不會出如今舊的消息中,因此(新的程序)要麼顯式地調用has_方法進行檢查,要麼在.proto文件中字段序號後面用[default=value]定義默認值。
· 並且:新的repeated字段不會出如今舊的消息中,(新的程序)無法判斷是(新的程序)把它設置成空了,仍是(舊的程序)根本就沒有設置這個字段,由於沒有has_方法!
相關文章
相關標籤/搜索