c++ proto_buf應用
阿新 • • 發佈:2018-11-09
person.proto
syntax = "proto2";
message Person {
required string name =1;
required int32 age = 2;
optional string email = 3;
repeated int32 array_value = 4;
}
使用protoc.exe把檔案生成c++類
./protoc --cpp_out=./ Person.proto
man.c原始檔
#include <string.h> #include <stdlib.h> #include <stdio.h> #include <iostream> #include <string> using namespace std; /* proto c++的高階使用 */ #include "../proto/person.pb.h" //用途:使用者傳遞一個訊息型別的字串,那麼這個工廠就能幫助我們構造出對應的類的例項 //"Person"字串-->構造出Person的例項-->返回的是一個基類Messge類的指標: //這個就是基類指標指向子類例項 //create_message 返回的 ,需要用delete來刪除msg物件例項 google::protobuf::Message* create_message(const char* typeName){ google::protobuf::Message* message = NULL; //根據名字,找到message的描述物件 const google::protobuf::Descriptor* descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); if (descriptor){ //根據描述物件到物件工廠裡面,生成對應的模板物件 const google::protobuf::Message* prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor); if (prototype){ message = prototype->New(); } } return message; } int main(int argc, char** argv){ //基類的messge指向person的例項 google::protobuf::Message* msg = create_message("Person"); //類似於這種操作 /*Person* blake = (Person*)msg; blake->set_name("blake"); printf("%s \n", blake->name().c_str());*/ /*每個message物件包含了兩個物件:Desc描述物件和反射物件 google::protobuf::Descriptor -->獲取message的描述資訊的 (//欄位規則 欄位資料型別 欄位名字 欄位標識號),描述資訊包含每一個field的描述 google::protobuf::Reflection -->使用它 + field描述,能get/set每個field的值 */ const google::protobuf::Descriptor* desc = msg->GetDescriptor(); const google::protobuf::Reflection* ref = msg->GetReflection(); //設定 const google::protobuf::FieldDescriptor* fdesc = desc->FindFieldByName("name"); ref->SetString(msg, fdesc, "hanchao"); fdesc = desc->FindFieldByName("age"); //通過名稱來查詢 fdesc = desc->FindFieldByNumber(2); //通過識別符號來查詢 ref->SetInt32(msg, fdesc, 30); fdesc = desc->FindFieldByName("email"); ref->SetString(msg, fdesc, "
[email protected]"); fdesc = desc->FindFieldByName("array_value"); ref->AddInt32(msg, fdesc, 101); ref->AddInt32(msg, fdesc, 202); ref->AddInt32(msg, fdesc, 303); ref->AddInt32(msg, fdesc, 404); //設定 end //遍歷Descriptor裡面的每一個field for (int i = 0; i < desc->field_count(); i++){ //獲取每一個field的描述物件 const google::protobuf::FieldDescriptor* fd = desc->field(i); //(1)獲取名字 printf("%s,,", fd->name().c_str()); if (fd->is_repeated()){ //表示當前field是一個數組,ref->FieldSize就是陣列的長度 for (int walk = 0; walk < ref->FieldSize(*msg, fd); walk++){ switch (fd->cpp_type()){ //cpp_type()當前field的型別 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: printf("%d\n", ref->GetRepeatedInt32(*msg, fd, walk)); break; case google::protobuf::FieldDescriptor::CPPTYPE_STRING: printf("%s\n", ref->GetRepeatedString(*msg, fd, walk).c_str()); break; } } continue; } switch (fd->cpp_type()){ //cpp_type()當前field的型別 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: printf("%d\n", ref->GetInt32(*msg, fd)); break; case google::protobuf::FieldDescriptor::CPPTYPE_STRING: printf("%s\n", ref->GetString(*msg, fd).c_str()); break; } } delete msg; //不用了需要delete刪除 system("pause"); return 0; }
1、create_message函式是傳入一個類的名稱,函式會生成這個名稱的類的物件(這個類前提是需要是真實存在的)
2、根據Descriptor獲取類的資訊,根據Reflection設定每一個欄位
const google::protobuf::Descriptor* desc = msg->GetDescriptor(); //獲取描述物件
const google::protobuf::Reflection* ref = msg->GetReflection(); //獲取反射物件
3、fdesc = desc->FindFieldByName("name"); // 獲取name物件
ref->SetString(msg, fdesc, "hello world"); //通過ref設定物件