1. 程式人生 > >c++ proto_buf應用

c++ proto_buf應用

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設定物件