簡要介紹和總結protobuf的一些關鍵點,從我以前作的ppt裏摘錄而成,但願能節省protobuf初學者的入門時間。這是一個簡單的Demo。html
Protobuf全稱Google Protocol Buffersjava
消息定義文件user_def.protopython
package user; message UserInfo { required int64 id = 1; optional string name = 2; repeated bytes nick_name = 3; }
編譯.proto,生成解析器代碼linux
protoc --cpp_out . user.proto // user_def.pb.h user_def.pb.cc protoc --java_out . user.proto // user/UserInfo.java
optional string name = 2
;c++
https://developers.google.com/protocol-buffers/docs/proto#scalargit
string vs. bytesgithub
.proto類型 | c++類型 | java類型 | 說明 |
---|---|---|---|
string | std::string | String | 必須是UTF-8或ASCII文本 |
bytes | std::string | ByteString | 任意的字節序列 |
反射是protobuf的一個重要特性,涉及到的類主要有:json
如下是一個根據消息名(包含package name)建立protobuf消息的C++函數,須要注意的是返回的消息必須在用完後delete掉。函數
Message* createMessage(const string &typeName) { Message *message = NULL; // 查找message的descriptor const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); if (descriptor) { // 建立default message(prototype) const Message *prototype = MessageFactory::generated_factory()->GetPrototype(descriptor); if (NULL != prototype) { // 建立一個可修改的message message = prototype->New(); } } return message; }
根據消息的字段名稱修改其值。以上面的user.UserInfo爲例,下面將一個新的UserInfo消息的其id字段設爲100。post
int main() { // 使用上面的函數建立一個新的UserInfo message Message *msg = createMessage("user.UserInfo"); if (NULL == msg) { // 建立失敗,多是消息名錯誤,也多是編譯後message解析器 // 沒有連接到主程序中。 return -1; } // 獲取message的descriptor const Descriptor* descriptor = msg->GetDescriptor(); // 獲取message的反射接口,可用於獲取和修改字段的值 const Reflection* reflection = msg->GetReflection(); // 根據字段名查找message的字段descriptor const FieldDescriptor* idField = descriptor->FindFieldByName("id"); // 將id設置爲100 if (NULL != idField) { reflection->SetInt64(msg, idField, 100); } // ... 其餘操做 // 最後刪除message delete msg; return 0; }
用createMessage建立一個空的消息後,最多見的使用場景是使用Message的ParseFromString或ParseFromIstream方法從字符串或流中讀取一個序列化後的message。
Message *msg = createMessage("user.UserInfo"); if (NULL != msg) { if (!msg->ParseFromString("... serialized message string ... ")) { // 解析失敗 ... } }