Google Protocol buffer 學習筆記.下篇-動態編譯
一 動態編譯
前文介紹了Protobuf的安裝及編譯方法,不過protobuf不僅提供了使用protoc進行靜態編譯的方法,也提供了動態編譯的方法
動態編譯 也就是說無須編譯
.proto
生成.pb.cc
和.pb.h
-
需要使用protobuf中提供的兩個標頭檔案, protobuf中標頭檔案的位置
/usr/local/include/google/protobuf
google/protobuf/compiler/importer.h
以及google/protobuf/dynamic_message.h
先看程式碼示例
#include <iostream>#include <string>#include <google/protobuf/compiler/importer.h>#include <google/protobuf/dynamic_message.h>class MyErrorCollector: public google::protobuf::compiler::MultiFileErrorCollector { virtual void AddError(const std::string & filename, int line, int column, const std::string & message){ // define import error collector printf("%s, %d, %d, %sn", filename.c_str(), line, column, message.c_str()); } };int main(){ google::protobuf::compiler::DiskSourceTree sourceTree; // source tree sourceTree.MapPath("", "/home/szw/code/protobuf/tmp2"); // initialize source tree MyErrorCollector errorCollector; // dynamic import error collector google::protobuf::compiler::Importer importer(&sourceTree, &errorCollector); // importer importer.Import("test.proto"); // find a message descriptor from message descriptor pool const google::protobuf::Descriptor * descriptor = importer.pool()->FindMessageTypeByName("lm.helloworld"); if (!descriptor){ perror("Message is not found!"); exit(-1); } // create a dynamic message factory google::protobuf::DynamicMessageFactory * factory = new google::protobuf::DynamicMessageFactory(importer.pool()); // create a const message ptr by factory method and message descriptor const google::protobuf::Message * tmp = factory->GetPrototype(descriptor); // create a non-const message object by const message ptr // define import error collector google::protobuf::Message * msg = tmp->New(); return 0; }
標頭檔案
<google/protobuf/compiler/importer.h>
包含了編譯器物件相關標頭檔案
<google/protobuf/dynamic_message.h>
包含了Message_Descriptor
和Factory
相關
首先初始化一個
DiskSourceTree
物件, 指明目標.proto
檔案的根目錄建立一個
MyErrorCollector
物件, 用於收集動態編譯過程中產生的編譯bug, 該物件需要根據proto提供的純虛基類派生, 並需要重寫其中的純虛擬函式, 使之不再是一個抽象類初始化一個
Importer
物件, 用於動態編譯, 將DiskSourceTree
和MyErrorCollector
的地址傳入將目標
.proto
動態編譯, 並加入編譯器池中可以透過
FindMessageTypeName()
和訊息名, 來獲取到目標訊息的Message_Descriptor
建立動態工廠, 並利用工廠方法
GetPrototype
和目標訊息的Message_Descriptor
獲取一個指標const message *
利用訊息例項指標的
New()
方法獲取到non-const message ptr
二 型別反射
型別反射即是根據欄位的名稱獲取到欄位型別的一種機制
protobuf自身便配備了型別反射機制
需要標頭檔案
<google/protobuf/descriptor.h>
與<google/protobuf/message.h>
下面的示例,結合了動態編譯以及型別反射機制
程式碼解析:
首先使用動態編譯機制,將test1.proto與test2.proto兩個檔案動態編譯進編譯池
根據訊息名獲取到目標訊息的descriptor
建立一個動態工廠,並利用訊息的descriptor獲取到
const Message * tmp
利用
const Message * tmp
的方法New()
獲取Message * msg
根據msg獲取反射器
Reflection
物件利用descriptor可以遍歷各個欄位, 並利用descriptor的
cpp_type()
方法獲取到每個欄位的型別, 並藉此進行反射填充
程式碼示例
proto檔案
// @file test1.protosyntax = "proto3"; package lm; message Player { int32 id = 1; string name = 2; repeated string hero = 3; }
// @file test2.protosyntax = "proto3";import "test1.proto"; package lm; message Game{ repeated Player player = 1; string gameName = 2; };
cpp
// @file test.cpp#include <iostream>#include <string>#include <google/protobuf/compiler/importer.h> // Importer DiskSourceTree MultiFileErrorCollector#include <google/protobuf/dynamic_message.h> // DynamicMessageFactory #include <google/protobuf/descriptor.h> // Desctriptor FiledDescriptor ... all descriptor#include <google/protobuf/message.h> // Message Reflection MessageFactoryclass MyErrorCollector: public google::protobuf::compiler::MultiFileErrorCollector { virtual void AddError(const std::string & filename, int line, int column, const std::string & message){ // define import error collector printf("%s, %d, %d, %sn", filename.c_str(), line, column, message.c_str()); } };int main(){ google::protobuf::compiler::DiskSourceTree sourceTree; // source tree sourceTree.MapPath("", "./"); // initialize source tree MyErrorCollector errorCollector; // dynamic import error collector google::protobuf::compiler::Importer importer(&sourceTree, &errorCollector); // importer importer.Import("test1.proto"); importer.Import("test2.proto"); // find a message descriptor from message descriptor pool const google::protobuf::Descriptor * descriptor = importer.pool()->FindMessageTypeByName("lm.Game"); if (!descriptor){ perror("Message is not found!"); exit(-1); } // create a dynamic message factory google::protobuf::DynamicMessageFactory * factory = new google::protobuf::DynamicMessageFactory(importer.pool()); // create a const message ptr by factory method and message descriptor const google::protobuf::Message * tmp = factory->GetPrototype(descriptor); // create a non-const message ptr object by const message ptr // define import error collector google::protobuf::Message * msg = tmp->New(); // get a reflection by msg const google::protobuf::Reflection * reflection = msg->GetReflection(); // travel the message by message_descriptor for (int i=0; i<descriptor->field_count(); ++i){ const google::protobuf::FieldDescriptor * fieldDescriptor = descriptor->field(i); if (fieldDescriptor->is_repeated()){ switch (fieldDescriptor->cpp_type()){ case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { reflection->AddInt32(msg, fieldDescriptor, 10); break; } case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { reflection->AddString(msg, fieldDescriptor, "abc"); } case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { printf("Here is a repeadted message: %sn", fieldDescriptor->full_name().c_str()); } case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { break; } } }else{ switch (fieldDescriptor->cpp_type()){ case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { reflection->SetInt32(msg, fieldDescriptor, 10); break; } case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { reflection->SetString(msg, fieldDescriptor, "abc"); } case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { printf("Here is a message: %sn", fieldDescriptor->full_name().c_str()); } case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { break; } case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { break; } } } } printf("nmsgn"); msg->PrintDebugString(); return 0; }
作者:neilzwshen
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4369/viewspace-2821348/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- google protocol buffer——protobuf的編碼原理二GoProtocol
- google protocol buffer——protobuf的使用特性及編碼原理GoProtocol
- 【編譯openjdk學習筆記】編譯JDK筆記
- 《圖解 Google V8》編譯流水篇——學習筆記(二)圖解Go編譯筆記
- Node中Buffer學習筆記筆記
- protocol buffer的高效編碼方式Protocol
- google protocol buffer——protobuf的基本使用和模型分析GoProtocol模型
- protocol bufferProtocol
- 動態規劃學習筆記動態規劃筆記
- google protocol buffer——protobuf的問題及改進一GoProtocol
- google protocol buffer——protobuf的問題和改進2GoProtocol
- Solidity語言學習筆記————2、使用編譯器Solid筆記編譯
- Python學習筆記6——動態型別Python筆記型別
- java反射之動態代理學習筆記Java反射筆記
- 彙編學習筆記筆記
- 前端後臺以及遊戲中使用Google Protocol Buffer詳解前端遊戲GoProtocol
- TarsGo支援Protocol BufferGoProtocol
- Protocol Buffer 使用指北Protocol
- TarsGo 支援 protocol bufferGoProtocol
- 解密gRPC: Protocol Buffer解密RPCProtocol
- 【BUFFER】Oracle buffer cache之 latch 學習記錄Oracle
- 動態dp複習筆記筆記
- Tomcat學習筆記—-本地部署servlet動態資源Tomcat筆記Servlet
- 《Grpc+Protobuf學習筆記》三、go使用docker編譯執行RPC筆記GoDocker編譯
- 彙編基礎學習筆記筆記
- React學習筆記-State(狀態)React筆記
- Java IO學習筆記一:為什麼帶Buffer的比不帶Buffer的快Java筆記
- Netty使用Google Protocol Buffer完成伺服器高效能資料傳輸NettyGoProtocol伺服器
- Spring Cloud OpenFeign整合Protocol BufferSpringCloudProtocol
- 編譯lua動態庫編譯
- [python學習手冊-筆記]004.動態型別Python筆記型別
- Solidity語言學習筆記————14、動態位元組陣列Solid筆記陣列
- 編譯原理讀書筆記編譯原理筆記
- 彙編學習筆記之轉移指令筆記
- Java動態編譯優化——提升編譯速度(N倍)Java編譯優化
- h5學習筆記:動態載入vconsole 除錯工具H5筆記除錯
- iOS逆向學習筆記 - 彙編(一) - 初識彙編iOS筆記
- AC自動機學習筆記筆記