ProtoBuf 反射詳解

2021-09-10 05:55:10 字數 2803 閱讀 8439

protocol buffer 簡稱 protobuf,是用於結構化資料序列化的靈活、高效、自動的方法,又如 xml,不過它更小、更快、也更簡單。你可以定義自己的資料結構,然後使用**生成器生成的**來讀寫這個資料結構。你甚至可以在無需重新部署程式的情況下更新資料結構。

本文主要介紹 protobuf 裡的反射功能,使用的pb版本為2.6.1,同時為了簡潔,對 repeated/extension 欄位的處理方法沒有說明。

最初是起源於這樣乙個問題:

給定乙個pb物件,如何自動遍歷該物件的所有字段?

即是否有乙個通用的方法可以遍歷任意pb物件的所有字段,而不用關心具體物件型別。

使用場景上有很多:

比如json格式字串的相互轉換,或者bigtable裡根據pb物件的字段自動寫列名和對應的value。

例如定義了pb messge型別person如下:

person person;

person.set_name("yingshin");

person.set_age(21);

能否將該物件自動轉化為json字串,或者自動的寫hbase裡的多列:

如果設定了新的字段,比如person.set_email("[email protected]"),則自動新增新的一列:

答案就是pb的反射功能

我們的目標是提供這樣兩個介面:

//從給定的message物件序列化為固定格式的字串

void serialize_message(const google::protobuf::message& message, std::string* serialized_string);

//從給定的字串按照固定格式還原為原message物件

各個類以及介面說明:

1.1 message

person是自定義的pb型別,繼承自message. messagelite作為message基類,更加輕量級一些。

通過message的兩個介面getdescriptor/getreflection,可以獲取該型別對應的descriptor/reflection。

1.2 descriptor

descriptor是對message型別定義的描述,包括message的名字、所有欄位的描述、原始的proto檔案內容等。

獲取所有欄位的個數:int field_count() const

獲取單個字段描述型別fielddescriptor的介面有很多個,例如

const fielddescriptor* field(int index) const;//根據定義順序索引獲取

const fielddescriptor* findfieldbynumber(int number) const;//根據tag值獲取

const fielddescriptor* findfieldbyname(const string& name) const;//根據field name獲取

1.3 fielddescriptor

fielddescriptor描述message中的單個字段,例如欄位名,字段屬性(optional/required/repeated)等。

對於proto定義裡的每種型別,都有一種對應的c++型別,例如:

enum cpptype else {

field = iter->second;

assert(!field->is_repeated());

switch (field->cpp_type()) {

#define case_field_type(cpptype, method, valuetype)

case google::protobuf::fielddescriptor::cpptype_##cpptype: {

reflection->set##method(

message,

field,

*(reinterpret_cast(value.c_str())));

std::cout name() (value.c_str())) enum_type()->findvaluebynumber(*(reinterpret_cast(value.c_str())));

reflection->setenum(message, field, enum_value_descriptor);

std::cout name() (value.c_str())) setstring(message, field, value);

std::cout name() mutablemessage(message, field);

parse_message(value, submessage);

break;

default: {

break;

protobuf反射機制

參考 google protocol buffers protobuf 是一款非常優秀的庫,它定義了一種緊湊的可擴充套件二進位制訊息格式,特別適合網路資料傳輸。它為多種語言提供 binding,大大方便了分布式程式的開發,讓系統不再侷限於用某一種語言來編寫。在網路程式設計中使用 protobuf 需...

Protobuf反射功能

include include include include include person.pb.h using namespace std string package typedef void callbackfunc const string type name,google protobu...

Protobuf協議格式詳解

protobuf 是google開源的乙個序列化框架,類似xml,json,最大的特點是基於二進位制,比傳統的xml表示同樣一段內容要短小得多。還可以定義一些可選字段,用於服務端與客戶端通訊。前面幾篇文章說了protobuf的用法,看到網上也沒有分析protobuf協議的文章,就利用一些時間寫了 p...