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>
class Base : public gce::reflection::reflectable<Base>
{
protected:
member(unsigned long long, length);
member_mutable(std::string, name);
member_array(char, buf1, 10);
member_array_mutable(char, buf2, 10);
member_static(int, level);
member_static_array(double, ds, 10);
public:
method(void, set_length, (long long l))
{
length = l;
}
method(void, set_name, (const std::string& str))
{
name = str;
}
method(unsigned long long, get_length, ())
{
return length;
}
method(std::string, get_name, ());
method(static int, get_level, ())
{
return level;
}
method(virtual void, do_something, ())
{
std::cout<<"Base class do_something invoked"<<std::endl;
}
method(std::string*, func1, (std::string* str, int& val))
{
std::cout<<"str:"<<*str<<"
val:"<<val<<std::endl;
return str;
}
method(std::shared_ptr<std::string>, func2, ())
{
return std::shared_ptr<std::string>
(new std::string("hello, shared_ptr"));
}
};
int Base::level = 0;
double Base::ds[10];
std::string Base::get_name()
{
return name;
}
int main()
{
Base base;
auto& base_class = base.get_class();
std::cout<<"class name:"<<base_class.get_name()<<std::endl;
std::cout<<"size:"<<base_class.get_size()<<std::endl;
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();
std::cout<<it->first<<",
type name:"<<member_class.get_name()<<",
size:"<<member_class. get_total_size()<<std::endl;
}
try {
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);
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;
std::cout<<"invoke func1:"<<*base_class.get_method
("func1").invoke<std::string*>(&base, &str, val)<<std::endl;
std::cout<<"invoke func2:"<<*base_class.get_method
("func2").invoke<std::shared_ptr<std::string> >(&base)<<std::endl;
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