65.9K
CodeProject 正在变化。 阅读更多。
Home

基于 C++11 和元编程的通用 C++ 反射引擎

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (11投票s)

2015年8月30日

Apache

2分钟阅读

viewsIcon

45297

downloadIcon

937

这是一个跨平台的通用 C++ 引擎,包括一个通用运行时和一个反射引擎。

引言

这个通用 C++ 引擎是一个跨平台的通用 C++ 引擎,目前包括一个通用运行时和一个反射引擎。其主要目的是为 C++ 语言提供反射能力。基于 C++11 和元编程,该反射引擎实现了 C++ 的一系列通用反射功能。

背景

众所周知,C++ RTTI 的反射能力非常有限,这在现代编程中变得越来越重要。因此,提高 C++ 的反射能力至关重要。不幸的是,除了创建全新的编译器之外,我们无法隐式地将反射能力添加到 C++ 中。因此,我们必须通过添加宏的方式来实现反射,而无需新的编译器。幸运的是,C++11 和元编程提供了非常容易探索反射的方式。

特点

  • 检查普通字段和 static 字段
  • 检查方法
  • 在不包含任何精确定义的情况下设置和获取字段值
  • 动态调用普通方法、虚方法和 static 方法并获取返回值
  • 动态检查类继承
  • 在没有头文件的情况下创建实例
  • 也支持模板类反射
  • 复杂对象的序列化

编译器和平台

  • Linux: g++ 版本 4.8.3 或更高版本,64 位
  • Windows: Microsoft Visual Studio 2010 或更高版本

编译器所需的 C++ 11 特性

  • Auto 和 nullptr 关键字
  • Lambda 表达式
  • 默认模板类型
  • 右值引用
  • 模板特性

构建

对于 g++

  • gce/trunk/builds/so/make.sh -> libgcrt.so libreflect.so

对于 Visual Studio

  • gce/trunk/builds/dll/gcrt/gcrt.vcxproj
  • gce/trunk/builds/dll/reflect/reflect.vcxproj

Using the Code

使用 gce::reflection 非常简单。

演示

#include <src/reflect/reflect.h>
#include <stdio.h>
#include <string>

//must inherit from gce::reflection::reflectable
class Base : public gce::reflection::reflectable<Base>
{
protected:
       //declare reflectable property
       member(unsigned long long, length);
       //declare reflectable property with mutable key word
       member_mutable(std::string, name);
       //declare reflectable property as array, with size 10
       member_array(char, buf1, 10);
       //declare reflectable property as array, with size 10 and mutable key word
       member_array_mutable(char, buf2, 10);
       //declare reflectable static property
       member_static(int, level);
       //declare reflectable static property as array, with size 10
       member_static_array(double, ds, 10);

public:
       //declare and implement reflectable method
       method(void, set_length, (long long l))
       {
           length = l;
       }

       //declare and implement reflectable method
       method(void, set_name, (const std::string& str))
       {
           name = str;
       }

       //declare and implement reflectable method
       method(unsigned long long, get_length, ())
       {
           return length;
       }

       //declare reflectable method
       method(std::string, get_name, ());

       //declare and implement reflectable static method
       method(static int, get_level, ())
       {
           return level;
       }

       //declare and implement reflectable virtual method
       method(virtual void, do_something, ())
       {
           std::cout<<"Base class do_something invoked"<<std::endl;
       }   

       //pointer and reference as parameters or return value
       method(std::string*, func1, (std::string* str, int& val))
       {
           std::cout<<"str:"<<*str<<" 
           val:"<<val<<std::endl;
           return str;
       }

       //std::shared_ptr as return value
       method(std::shared_ptr<std::string>, func2, ())
       {
           return std::shared_ptr<std::string>
           (new std::string("hello, shared_ptr"));
       }
};

//define static property
int Base::level = 0;
double Base::ds[10];

//implement reflectable method out of its class body
std::string Base::get_name()
{
    return name;
}

int main()
{
       Base base;
       //get the class of Base
       auto& base_class = base.get_class();
       //print the class name
       std::cout<<"class name:"<<base_class.get_name()<<std::endl;
       //print the class size
       std::cout<<"size:"<<base_class.get_size()<<std::endl;

       //list all properties
       auto& members = base_class.members();
       std::cout<<"property list:"<<std::endl;
       for(auto it=members.begin(); it!=members.end(); ++it)
       {
              auto& member_class = it->second.get_class();
              //must use get_total_size here
              std::cout<<it->first<<", 
              type name:"<<member_class.get_name()<<", 
              size:"<<member_class. get_total_size()<<std::endl;
       }

       try //try-catch is required
       {
              //invoke method, we need to specify the return type as template type.
              //numeric 10 refers to int implicitly, 
              //so this argument must be specified unsigned long long explicitly
              base_class.get_method("set_length").invoke<void>(&base, (unsigned long long)10);
              std::string name = "Tom";
              base_class.get_method("set_name").invoke<void, Base, std::string>(&base, name);

              //invoke method and print return value
              std::cout<<"invoke get_length:"<<base_class.get_method
              ("get_length").invoke<unsigned long long>(&base)<<std::endl;
              std::cout<<"invoke get_name:"<<base_class.get_method
              ("get_name").invoke<std::string>(&base)<<std::endl;

              std::string str = "string pointer";
              int val = 10;
              //return type is string pointer
              std::cout<<"invoke func1:"<<*base_class.get_method
              ("func1").invoke<std::string*>(&base, &str, val)<<std::endl;
              //return type is std::shared_ptr<std::string>
              std::cout<<"invoke func2:"<<*base_class.get_method
              ("func2").invoke<std::shared_ptr<std::string> >(&base)<<std::endl;

              //invoke static method, instead of passing instance, 
              //we just need to pass nullptr, which must be interpreted to Base type explicitly.
              std::cout<<"invoke static get_level:"<<base_class.get_method
              	("get_level").invoke<int>((Base*)nullptr)<<std::endl;
       }
       catch(std::exception& e)
       {
              std::cout<<e.what()<<std::endl;
       }
       return 0;
}

该程序的输出将是

还有一些演示代码来展示该引擎提供的功能

  • 演示 2(动态调用)
  • 演示 3(单继承)
  • 演示 4(多重继承,即菱形继承)
  • 演示 5(模板类)
  • 演示 6(动态实例)
  • 演示 7(序列化)

有关更多详细信息和演示代码,请下载发布文件和文档。

此版本是一个 Beta 版本,欢迎提出任何问题或反馈。

非常感谢!

Bug 历史

根据错误报告,这是错误修复历史的列表。请确保下载最新版本。谢谢!

版本 0.53

修复了“'__call_constructor' 未在此范围内声明”的问题

修复了名称冲突

版本 0.51

修复了演示代码

 

© . All rights reserved.