BZ易风

导航

 

Message对象

1: 每一个Message对象都包含两个对象:
(1)google::protobuf::Descriptor 描述对象,是Message所有Filed的一个集合,它又包含了
FieldDescriptor 对象; 每个filed都对应一个FieldDescriptor;
(2)google::protobuf::Reflection 反射对象, 通过它 + FieldDescriptor, 能set/get filed对象的值;

2: 每一个Message对象,可以通过统一的对象工厂来构建, 根据协议生成了代码后,只要传入Message的名字,就能构建出对应的Message的类的实例;

#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>

#include <iostream>
#include <string>
using namespace std;
#include "../proto/person.pb.h"

#if 0
int main(int argc, char** argv)
{
    //1.定义要传送数据的对象  对应message后跟的名字
    Person p;  
    //2.初始化对象
    p.set_name("大圣");
    p.set_email("wukong@163.com");
    p.set_age(1700);

    cout << p.name() << " " << p.age() << " " << p.email() << endl;
    //3.将这个数据对象序列化
    string out;
    p.SerializeToString(&out);

    //4.使用string对象里面存放的数据,反序列化数据对象
    Person monkey;
    monkey.ParseFromString(out);
    cout << monkey.name() << " " << monkey.age() << " " << monkey.email() << endl;
    system("Pause");
    return 0;
}
#else
//传递一个信息类型的字符串,那么这个工厂就会帮我们构造出一个对应的类的实例
//"Person"字符串-->Person的实例 -->返回的是一个基类Message类的指针
//基类指针 指向子类实例
//create_message -->delete 来删除对象实例
google::protobuf::Message* create_message(const char* typeName) {
    //message类
    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)
{
    //基类的message-->Person类的实例
    google::protobuf::Message* msg = create_message("Person");

    /*
    Person* hou = (Person*)msg;
    hou->set_name("大圣");
    cout << hou->name() << endl;
    */

    /*
        每个message对象包含两个对象:
        google::protobuf::Descriptor 描述对象-->获取message的描述信息 字段名以及类型等-->包含每一个field的描述
        google::protobuf::Reflection 反射对象--> 使用这个对象 + field描述, 能get/set每个field的值
    */

    const google::protobuf::Descriptor* des = msg->GetDescriptor();
    const google::protobuf::Reflection* ref = msg->GetReflection();

    //设置
    // name
    // 1. 通过des获取
    const google::protobuf::FieldDescriptor* fd_des = des->FindFieldByName("name"); //通过字段名字设置数据
    // 2.通过ref进行设置
    ref->SetString(msg, fd_des, "大圣");

    //age
    fd_des = des->FindFieldByNumber(2); //通过字段标识号设置数据
    ref->SetInt32(msg, fd_des, 1500);
    //email
    fd_des = des->FindFieldByName("email");
    ref->SetString(msg, fd_des, "wukong@163.com");
    //数组 使用AddInt32一个一个追加进去
    fd_des = des->FindFieldByName("set");
    ref->AddInt32(msg, fd_des, 1);
    ref->AddInt32(msg, fd_des, 2);
    ref->AddInt32(msg, fd_des, 3);
    ref->AddInt32(msg, fd_des, 4);

    //获取
    for (int i = 0; i < des->field_count(); i++)
    {
        //获取每一个field描述对象
        const google::protobuf::FieldDescriptor* fd = des->field(i);
        //(1) 获取名字
        cout << fd->name() << endl;     //字段名字 不是数据 如:name age
        cout << fd->type_name() << endl;     //类型
        cout << fd->cpp_type_name() << endl;     //c++类型 bytes被换成了string
        // 判断字段规则
        // fd->is_repeated() 是否是数组
        // fd->is_optional() 是否是非必须
        // fd->is_required() 是否是必须
        if (!fd->is_repeated()) {
            //获取数据
            switch (fd->cpp_type())
            {
            case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32:
                cout << ref->GetInt32(*msg, fd) << endl;
                break;
            case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING:
                cout << ref->GetString(*msg, fd) << endl;
                break;
            }
        }
        else {
            for (int j = 0; j < ref->FieldSize(*msg, fd); j++)  //ref->FieldSize(*msg, fd)获取数组长度
            {
                switch (fd->cpp_type())
                {
                case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32:
                    cout << ref->GetRepeatedInt32(*msg, fd,j) << " ";  //使用GetRepeatedInt32 便利数组
                    break;
                case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING:
                    cout << ref->GetRepeatedString(*msg, fd,j) << " ";
                    break;
                }
            }
            cout << endl;
        }
        
       

        cout << fd->number() << endl;        //获取字段标识号
    }
    //删除
    delete msg;
    system("Pause");
    return 0;
}
#endif

 

posted on 2021-09-14 16:38  BZ易风  阅读(1887)  评论(0编辑  收藏  举报