基于 C++11 和元编程的通用 C++ 反射引擎
这是一个跨平台的通用 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
修复了演示代码