side image

RTTR - Run Time Type Reflection

image

A library which adds the missing reflection feature to C++.

Introduction

The run time type reflection (RTTR) library adds the missing feature of reflection to C++. That means the programmer can introspect an object at runtime of what kind of properties, methods and constructors it consist. This is extremely useful when a tight but also high dynamic coupling between software modules is required. The main use cases are for example serialisation, UI creation, binding to arbitrary programming languages (JavaScript, Lua etc.) and network communication.

It works without any extra preprocess pass to reflect a type, only standard C++11 language features are used. However, in order to reflect a types it is required to manually register the classes with its properties and methods. While registering methods it is usually not necessary to know the exact signature, since the library will generate a wrapper class for this depending on the compile-time type of the method. To avoid header pollution, the registration process should be done completely in the cpp file, there is no need to derive from some super base class.

For developing this library I was inspired by the reflection systems of C# and Qt.

Features

RTTR supports:

  • a faster and across shared libraries working replacement of rtti
  • classes; with single-, multiple- and virtual-inheritance (requires one macro placement inside class)
  • constructors (arbitrary argument count)
  • properties
  • methods (virtual, abstract, overloaded, arbitrary argument count)
  • enums (C++11 enum class)
  • arrays (incl. raw-arrays; arbitrary dimension count)
  • ability to invoke properties and methods of classes from any arbitrary class level
  • no header pollution; the reflection information is created in the cpp file to minimize compile time when modifying the data
  • working with custom types without the need of having the declaration of the type available at compile time (useful for plugins)
  • possibility to add additional metadata to all reflection objects
  • adjust binding behaviour through return value policies
  • minimal macro usage
  • no exceptions (this feature come with cost and is also regularly disabled on consoles)
  • no external compiler or tool needed, only standard ISO C++11

Portability

RTTR is compiled and tested on following platforms:

  • Microsoft Visual C++ 12 (2013), Update 4 - x32 and x64
  • gcc 4.8.1 - x32 and x64

Example

Mesh.h
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
#include <rttr/type>
struct Mesh
{
  Mesh();
  Mesh(const std::string& name);
  Vector3d getPosition() const;
  void setPosition(const Vector3d& pos);
  enum E_TransformSpace
  {
    TS_LOCAL,
    TS_PARENT,
    TS_WORLD
  };
  
  void setDirection(const Vector3d &vec, E_TransformSpace ts = TS_LOCAL);
  
  private:
    Vector3d _pos;
};

RTTR_DECLARE_STANDARD_TYPE_VARIANTS(Mesh) // to register the type


Mesh.cpp
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
#include "Mesh.h"
#include <rttr/reflect>
#include <iostream>
using namespace rttr;

// register the class Mesh before main is called
RTTR_REGISTER
{
  class_<Mesh>()
    .constructor<>()
    .constructor<const std::string&>()
    .enumeration<E_TransformSpace>({{"TS_LOCAL", TS_LOCAL},
                                    {"TS_PARENT", TS_PARENT},
                                    {"TS_WORLD", TS_WORLD}})
    .property("pos", &Mesh::getPosition, &Mesh::setPosition)
    .method("setDirection", &Mesh::setDirection);
}

int main()
{
  Mesh obj;
  const type mesh_type = type::get(obj);
  std::cout << mesh_type.get_name() << std::endl;     // prints "Mesh"
  
  // sets/gets a property
  property pos = mesh_type.get_property("pos");
  pos.set_value(obj, Vector3d(1,2,3));                // here we set the value
  variant var_pos = pos.get_value(obj);               // here we get the value
  
  Vector3d& vec = var_pos.get_value<Vector3d>();      // vec == Vector3d(1,2,3)
  
  // invoke a method
  method meth_dir = mesh_type.get_method("setDirection");
  meth_dir.invoke(obj, Vector3d(1,2,3), Mesh::TS_WORLD);
  
  // retrieve all properties
  for (const auto& prop : mesh_type.get_properties())
  {
      std::cout << prop.get_name(); // prints all property names of the type Mesh
  }
  
  for (const auto& meth : mesh_type.get_methods())
  {
      std::cout << meth.get_name(); //  prints all method names of the type Mesh
  }
  
  return 0;
}

License

RTTR is licensed under the MIT license. Have fun.

Documentation

Here is a link to the documentation of RTTR:
Documentation - 0.9.0

Download

Download - rttr-src-0.9.0.zip

Update, 23.12.2015:

I finally managed to release a new version of RTTR. Find more information on its own website: www.rttr.org

Update, 12.04.2015:

I just want to inform your, that I am working right busy on the 1.0 release of RTTR. There it will be no longer necessary to register manually your types with the macro. Additionally, it will be possible to register the base class hierarchy outside of the class, quite handy for 3rd party code. And a lot of other cool features, stay tuned. I expect the release in the next couple of months.