• protobuf 反射使用总结


    背景

    反射是指可以动态获取任意类的属性和方法以及动态调用任意对象的属性和方法的机制。C++ 本身没有反射机制,但通过 protobuf 可以在运行时获取和修改对象的字段。

    反射相关类

    ①.Descriptor
    Descriptor 包含了对 message 的描述,以及其所有字段的描述。
    ②.FieldDescriptor
    FieldDescriptor 包含了对 message 中单个字段的详细描述。
    ③.Reflection
    Reflection 提供了对 message 中单个字段进行动态读写的方法。

    使用反射创建 message

    ①.概述
    DescriptorPool 中存储了所有 message 的元信息;
    MessageFactory 是一个实例创建工厂,可以根据 message 的描述信息得到其默认实例;
    根据类型的默认实例可以创建同类型的 message 对象;
    mesaage 的类型名称要带上其 package 名称。

    ②.示例 message

    message DemoMsg
    {
       int32 id = 1;
       string name = 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ③.使用反射创建 message

    auto getMessageByName = [](const string & msgType){
         auto desc = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(msgType);
         if (!desc) return shared_ptr<google::protobuf::Message>(nullptr);
         auto instance = google::protobuf::MessageFactory::generated_factory()->GetPrototype(desc);
         if (!instance) return shared_ptr<google::protobuf::Message>(nullptr);
         std::shared_ptr<google::protobuf::Message> msg = std::shared_ptr<google::protobuf::Message>(instance->New());
         return msg;
    };
    string msgType = "protoTest.DemoMsg";
    auto msg = getMessageByName(msgType);
    if (msg)  cout << msgType << " 创建成功" << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    使用反射读写字段

    ①.概述
    根据 message 的描述可以得到字段的描述;
    使用 message 的反射和字段的描述可以进行字段值的读写。
    ②.使用反射设置字段值

    string msgType = "protoTest.DemoMsg";
    auto msg = getMessageByName(msgType);auto desc = msg->GetDescriptor();
    auto refl = msg->GetReflection();
    auto field = desc->FindFieldByName("name");
    refl->SetString(msg.get(), field, "1234");
        
    cout << msg->DebugString() << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    ③.使用反射读取字段值

    if( refl->HasField(*msg, field) )
            cout <<  refl->GetString(*msg, field) << endl;
    
    • 1
    • 2

    在这里插入图片描述

    使用反射遍历字段

    ①.概述

    使用反射可以在运行时对 message 的所有字段进行遍历。

    ②.使用反射遍历字段

    protoTest::DemoMsg msg;
        
    auto desc = msg.GetDescriptor();
    auto refl = msg.GetReflection();int size = desc->field_count();
    for (int i = 0; i < size; ++i)
    {
        auto field = desc->field(i);
        cout << field->name() << " " << field->type_name() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    【axios网络请求库】认识Axios库;axios发送请求、创建实例、创建拦截器、封装请求
    C++基础01
    C\C++ 使用RapidJSON库,轻松解析和生成JSON
    Apache Ignite 集群安装
    基于 ANFIS 的非线性回归(Matlab代码实现)
    神经网络bp算法应用,bp神经网络动量因子
    nginx https 如何将部分路径转移到 http
    2022下半年软考什么时候开始报名?
    LeetCode ❀ 66. 加一 / python
    案例|航海知识竞赛需求沟通整理
  • 原文地址:https://blog.csdn.net/lizhichao410/article/details/126133516