首页 > 其他分享 >Runtime Reflection

Runtime Reflection

时间:2024-02-02 10:48:37浏览次数:27  
标签:std Node Reflection MetaType int void Runtime string

参考:

1. A Flexible Reflection System in C++: Part 1 (preshing.com)

2. C++ Reflection | Austin Brunkhorst 

2做的更好。反射的代码是自动生成的。

目的

为了学习这个理念,先是从0 感受一个最简单的实现:

假设:

struct Node {
    std::string key;
    int value;
}

可以实现:

int main() {
    using namespace std::string_literals;

    Node node = {"apple",3};
    auto *metaStruct = dynamic_cast<RF::MetaType_Struct*>(RF::MetaTypeResolver<Node>::get());
    metaStruct->dump(&node);
    std::cout << "after changed\n";
    metaStruct->setMember(&node, "key", "Houdini"s);
    metaStruct->setMember(&node, "value", 123);
    metaStruct->dump(&node);
    return 0;
}

运行时输出:

Node{
    key=std::string{apple}
    value=int{3}
}
after changed
Node{
    key=std::string{Houdini}
    value=int{123}
}

 

V0 一个结构体 2个成员:

#include <iostream>
#include <vector>
#include <any>
#include <concepts>
namespace RP_Reflection{
    struct MetaType{
        std::string typeName; // for example int, std::string
        size_t size;
        MetaType(std::string valueTypeName, size_t size) : typeName{std::move(valueTypeName)}, size{size} {}
        virtual ~MetaType() =default;
        [[nodiscard]] virtual std::string getFullTypeName() const { return typeName;}
        virtual void dump(const void *data) const= 0;
        virtual void set(void *data, std::any ) {}
    };
    // meta->string
    struct MetaType_Int: MetaType{
        explicit MetaType_Int() : MetaType{"int", sizeof(int)}{}
        void dump(const void *ptr) const override{ std::cout <<"int{" << *(static_cast<const int*>(ptr)) << "}";}
        void set(void *ptr, std::any v ) override{
            *static_cast<int*>(ptr) = std::any_cast<int>(v);
        }
    };
    // meta->int
    struct MetaType_String: MetaType{
        MetaType_String() : MetaType("std::string", sizeof(std::string)){}
        void dump(const void *ptr) const override{ std::cout <<"std::string" << "{"<< *(static_cast<const std::string*>(ptr))<< "}";}
        void set(void *ptr, std::any v ) override{
            *static_cast<std::string*>(ptr) = std::move(std::any_cast<std::string>(std::move(v)));
        }
    };
    // meta->struct
    struct MetaType_Struct: MetaType{
        struct MetaMember{
            std::string fieldName;
            size_t offset;
            MetaType *type;
        };
        std::vector<MetaMember> members;

        explicit MetaType_Struct(void (*init)(MetaType_Struct *)): MetaType{"",0} {
            init(this);
        }

        void dump(const void *ptr)const override{
            std::cout << typeName << "{"<< std::endl;
            for(const auto &member : members){
                std::cout << std::format("    {}=", member.fieldName);
                member.type->dump(static_cast<const char*>(ptr) + member.offset);
                std::cout << "\n";
            }
            std::cout << "}\n";
        }

        void setMember(void *ptr,const char *name, std::any data){
            for(auto &member : members){
                if(member.fieldName != name ) continue;
                member.type->set( static_cast<char*>(ptr) + member.offset, std::move(data));
            }
        }
    };

    // Declare the function template that handles primitive types such as int, std::string, etc.:
    template<typename T>
    MetaType *GetPrimitiveMetaType();

    // check class is MetaType
    template<typename T>
    concept isMetaType = std::is_base_of_v<MetaType, std::remove_cvref_t<std::remove_pointer_t<T>> >;

    // check a class that was reflected
    template<typename T>
    concept isReflectedClass = requires(T){
        { T::reflection } -> isMetaType;
    };

    // TemplateMethod Get MetaType
    template<typename T>
    struct MetaTypeResolver{
        static MetaType *get(){
            if constexpr (isReflectedClass<T>)
                return &T::reflection;
            else return GetPrimitiveMetaType<T>();
        }
    };

    template<>
    MetaType *GetPrimitiveMetaType<int>(){
        static MetaType_Int metaInt;
        return &metaInt;
    }
    template<>
    MetaType *GetPrimitiveMetaType<std::string>(){
        static MetaType_String metaStr;
        return &metaStr;
    }

} // end of namespace


namespace RF = RP_Reflection;

struct Node {
    std::string key;
    int value;

    // REFLECTION CODE HERE
    static RF::MetaType_Struct reflection;
    static void initReflection(RF::MetaType_Struct *);
};

RF::MetaType_Struct Node::reflection(Node::initReflection);

void Node::initReflection(RF::MetaType_Struct *ms) {
    ms->typeName = "Node";
    ms->size = sizeof(Node);
    ms->members = {
            {"key", offsetof(Node, key), RF::MetaTypeResolver<decltype(Node::key)>::get()},
            {"value", offsetof(Node, value), RF::MetaTypeResolver<decltype(Node::value)>::get()},
    };
}

int main() {
    using namespace std::string_literals;

    Node node = {"apple",3};
    auto *metaStruct = dynamic_cast<RF::MetaType_Struct*>(RF::MetaTypeResolver<Node>::get());
    metaStruct->dump(&node);
    std::cout << "after changed\n";
    metaStruct->setMember(&node, "key", "Houdini"s);
    metaStruct->setMember(&node, "value", 123);
    metaStruct->dump(&node);
    return 0;
}

 输出:

Node{
    key=std::string{apple}
    value=int{3}
}
after changed
Node{
    key=std::string{Houdini}
    value=int{123}
}

 

标签:std,Node,Reflection,MetaType,int,void,Runtime,string
From: https://www.cnblogs.com/gearslogy/p/18001393

相关文章

  • ILRuntime是如何实现热更新的
    一、ILRuntime的基本原理ILRuntime的基本原理是将C#代码编译成IL代码,然后在运行时通过IL解释器将其转换成机器码执行。这种方式与传统的AOT(AheadofTime)编译方式不同,传统的AOT编译方式是在编译时将C#代码编译成机器码,然后在运行时直接执行机器码。由于ILRuntime是在运行时解释......
  • ILRuntime编码中如何注意性能问题
    一、避免频繁的反射操作在使用ILRuntime时,我们需要频繁地进行反射操作,例如获取类型、获取方法、获取属性等等。反射操作是非常耗费性能的,所以我们需要尽可能地避免频繁的反射操作。例如,我们需要获取一个类型的所有属性,我们可以使用以下代码:PropertyInfo[]properties=typeof......
  • 安装MySQL出现由于找不到vcruntime140_1.dll,无法继续执行代码的提示
    问题描述:在安装MySQL服务的时候,执行安装命令提示如下的错误信息。解决方法:通过分析可以知道,是由于缺少了vcruntime140_1.dll动态链接库文件,这是windows缺少vc_redist.x64.exe程序导致的服务安装错误,与我们要安装的MySQL服务并没有关系。(如果您的安装过VS类型的工具,就不会提示该......
  • Maven学习之路--依赖范围scope 对于该包的依赖范围作用域,取值有:test、compile、provid
    Maven学习之路--依赖范围scope对于该包的依赖范围作用域,取值有:test、compile、provided、runtime。scope默认取值为compile。\   <scope></scope>表示对于该包的依赖范围作用域,取值有:test、compile、provided、runtime。scope默认取值为compile。<scope>test</scope>。te......
  • k8s中controller-runtime并发Reconcile分析
    §0x01起因开发控制器时,团队内一直在讨论是否需要为单个控制器对象添加并发控制(即加锁),最终把controller-runtime框架中并发数改为1,同时启用了k8s的leaderelection机制保证只有单实例来规避并发的可能。这种做法其实是有问题的,没有搞清楚controller-runtime框架本身是......
  • onnxruntime输出模型中间层的结果
    defget_layer_output(model,image):ori_output=copy.deepcopy(model.graph.output)fornodeinmodel.graph.node:foroutputinnode.output:model.graph.output.extend([onnx.ValueInfoProto(......
  • ILRuntime是如何与Unity互相调用的
    ILRuntime是一个跨平台CLR实现,它可以在多个平台上运行C#代码,包括Android、iOS、Windows、Linux等等。ILRuntime的实现方式是将C#代码编译成IL代码,然后在运行时通过JIT或AOT的方式将IL代码转换为机器代码,从而实现跨平台的效果。ILRuntime的主要功能包括热更新、动态加载、代码加密......
  • Java中System类和Runtime类常用方法和属性
    ​ Java中,System类和Runtime类提供了一些关键的功能,用于与底层操作系统以及运行时环境进行交互。System类是Java标准库中的一个类,提供了对JVM的一些基本访问和控制方法。Runtime类实例封装了运行时环境。为Java程序提供了与底层系统交互的强大工具,但也需要谨慎使用以避免潜......
  • 【Android】通过grantRuntimePermission、revokeRuntimePermission获取和回收运行时权
     需求:不需要用户点击允许按钮直接获取READ_PHONE_STATE等权限分析:因为用户可以在手机中通过打开设置-应用-选择具体应用-权限界面,手动打开用户所需要的权限(界面效果如图),我就想我怎么样可以在代码中模拟点击按钮打开权限的操作,于是我就去查看源码。 第一步:通过adb......
  • 加载动态库onnxruntime
    publicstaticIntPtrOnnxRuntimeImportResolver(stringlibraryName,Assemblyassembly,DllImportSearchPath?searchPath){//调试信息LogHelper.NlogTrace(libraryName);if(libraryName!="onnxruntime")......