• 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

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    Linux开发板移植FTP服务器和OpenSSH时发现的问题
    pyautogui模拟鼠标拖动选中文字的基本知识(附Demo)
    成功解决TypeError: only size-1 arrays can be converted to Python scalars
    钉钉stream机器人-实操详细教程
    【how2j练习题】css部分课后练习
    python判断是否到了文件尾
    Kubernetes最小单元Pod的生命周期
    7.5面试问答
    javascript复习之旅 9.1 从0到1认识`call apply`
    spring-Bean管理-springboot原理-Maven高级
  • 原文地址:https://blog.csdn.net/lizhichao410/article/details/126133516