A General C++ Reflection Engine Based on C++11 and Meta Programming
This is a cross-platform general C++ engine, including a general runtime and a reflection engine.
- Download reflection_0_5_3.zip - 372.3 KB
- Download Instruction_for_general_C___Reflection_Engine.zip - 264.1 KB
Introduction
This general C++ engine is a cross-platform general C++ engine, including a general runtime and a reflection engine by now. Its main purpose is to provide reflection capabilities to C++ language. Based on C++11 and Meta Programming, this reflection engine implements a serial of general reflection functionalities for C++.
Background
As we all know, C++ RTTI has very limited ability to make reflection, which definitely becomes more and more important in modern programming. So it’s quite critical to improve the reflection ability for C++. Unfortunately, we cannot add reflection ability to C++ implictly, except creating a brand new compiler. So we have to reflect by adding macros without new compiler. Fortunately, C++11 and Meta Programming provide very easy ways to explore reflection.
Features
- Examine normal and
static
fields - Examine methods
- Set and get field values without including any exact definition
- Invoke normal, virtual and
static
methods and get return value dynamically - Examine class inheritance dynamically
- Create instance without any header files
- Support template class reflection as well
- Serialization for complex object
Compilers and Platforms
- Linux: g++ version 4.8.3 or higher, 64-bit
- Windows: Microsoft Visual Studio 2010 or higher
C++ 11 features required for compiler:
- Auto and
nullptr
keyword - Lambda expression
- Default template type
- Right value reference
- Template traits
Builds
For g++:
- gce/trunk/builds/so/make.sh -> libgcrt.so libreflect.so
For Visual Studio:
- gce/trunk/builds/dll/gcrt/gcrt.vcxproj
- gce/trunk/builds/dll/reflect/reflect.vcxproj
Using the Code
It’s quite easy to use gce::reflection
.
Demo
#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;
}
The outputs of this program would be:
There are a few more demo codes to show what this engine provides:
- Demo 2 (dynamic invoke)
- Demo 3 (single inheritance)
- Demo 4 (multiple inheritances, i.e., diamond hierarchy)
- Demo 5 (template class)
- Demo 6 (dynamical instance)
- Demo 7 (serialization)
For more details and demo codes, please download the release file and document.
This release is a beta version, any problems or feedback are very welcome.
Thanks very much!
Bug History
According to the bug reports, here's the list of the bug fixing history. Please make sure to download the latest version. Thanks!
version 0.53:
fix '__call_constructor’ was not declared in this scope
fix name conflict
version 0.51:
fix demo code