Reflection for C++

Posted by Kaya Kupferschmidt • Monday, February 26. 2007 • Category: C++
One hot topic I am currently busy in, is reflection for C++. Reflection for a computer language means that you can access all types toegther with their methods and members at runtime using a simple string-based interface. Such a feature especially simplifies binding scripting-languages to a program by providing one wrapper that operates on the reflection information instead of binding each class, method or function by hand. Other possible usages are remote-method-invocations, serialisation, XML based configurations etc.

C++ offers only some very basic runtime type information (RTTI) out of the box and lacks full reflection. There are some projects on the net that try to close this gap (most notably the Reflex framework), but none of them really seem to be as powerful, flexible and easy-to-use as their native counterparts in Java or C#.

Dimajix's framework Magnum soon will contain some new modules that try to fill this gap, by offering the following tools:

  • A generic Meta-Compiler based upon gccxml together with a specialised XML-based transformation language.

  • Non-intrusive, full reflection for all public elements of any C++ program given in source.

  • A Java-like scripting language built on top of the reflection together with a custom bytecode compiler.


With these tools, one can easily add generic scripting capabilities to any C++ program with only some little one-time effort. Plus it is possible to use the Metacompiler for automatically transforming any type-information given in C++ headers in any kind of text-based files, by providing a set of transformation rules which will be applied to the C++ metainformation generated with gccxml.

The new package is not completely finished yet, there are some features still missing, but work is steadily progressing. For a preview, you can simply check out the latest version of Magnum using Subversion at svn://subversion.dimajix.de/magnum.

Status of Magnum

Posted by Kaya Kupferschmidt • Saturday, January 13. 2007 • Category: C++
A short intermission with a status report of Magnum. Finally I put up a public SVN repository which can be reached under svn://dimajix.de/magnum. The repository has public read access for everyone and is synched with my private development repository every night, so it is always almost up-to-date.

The most important feature that will be included in the next release version is full reflection. This means that one can access the complete type information including classes, structs, unions, enums, methods, functions, fields and variables via a dynamic interface at runtime. You can even invoke any method or create new instances of arbitrary objects. This should make it rather easy to make up a small scripting language which can access all types defined in Magnum.

This is a really huge undertaking, but most of the really hard stuff is already working (you can download the newest version via Subversion, as indicated above.). Still missing is some intelligent automatic argument casting for method-invocation (so you do not have to care about the exact needed types), some fixes for non-public class members and - most importantly - the integration into the build system.

The really special about my implementation of the reflection is that you will not need to modify your source-code (at least I try really hard to avoid the need of changes to the source code for which reflection is to be generated.) to make your classes accessible via reflection. The meta-compiler, which reads in all headers and creates some cpp files containing the needed runtime information for reflection, is also outstanding in that it uses a generic XML-based language to transform the meta-information parsed from the original header files into a new text-based output file. The metacompiler is not tied to my implementation of reflection and can (and will) be used for many other automatic header-transformations. For example one could write an XML template that generates serialisation code for arbitrary classes (this actually shouldn't be too hard). Other possible uses include the generation of COM or .Net wrappers (or for any other scripting language), etc.

Inheritance, Constructors, Virtual Methods and typeid

Posted by Kaya Kupferschmidt • Wednesday, May 3. 2006 • Category: C++
When working with inheritance and virtual methods, there might be some surprises when one tries to call a virtual method inside a constructor - and this is the reasons why one should never ever call virtual methods inside a constructor or inside a destructor.

Consider the following simple code
class A {
public:
    A() {
        printf("A::A() calls ");
        f();
    }
    ~A() {
        printf("A::~A() calls ");
        f();
    }
    virtual void f() {
        printf("A::f()\n");
    }
};


class B : public A {
public:
 	B() {
     		printf("B::B() calls ");
     		f();
 	};
 	~B() {
     		printf("B::~B() calls ");
     		f();
 	};
 	virtual void f() {
     		printf("B::f()\n");
 	};
};	


void main(void) {
 	B obj;
 	obj.f();
};

Continue reading "Inheritance, Constructors, Virtual Methods and typeid"

New cast operators with additional features

Posted by Kaya Kupferschmidt • Friday, April 7. 2006 • Category: C++
C++ already has a rich set of casting operatos, ranging from old-style C casts, over static_cast, dynamic_cast and the almost-never-to-be-used reinterpret_cast. Sometimes it might be convenient to have something similar like a dynamic_cast but with another behaviour if the cast fails. For example one might want to get an exception if a specific cast is not possible.

It turns out that this is pretty easy using templates with the following code

template<class T,class S> T* throwing_cast(S* s) {
   T* result = dynamic_cast<T>(s);
   if (!result)
     throw bad_cast_exception();
   return result;
}

ClassA* a = new ClassB();
ClassB* b = throwing_cast<ClassB>(a);

But we still can do better than this, because we might want to configure which exception should be thrown on a casting failure. The code above can be easily modified to:

Continue reading "New cast operators with additional features"

Scripting your Applications

Posted by Kaya Kupferschmidt • Monday, March 20. 2006 • Category: C++
In my last entry I was talking about a neat tool generating reflection information for arbitrary C++ programs. Today I found another useful tool that is somewhat related to reflection, namely scripting. There are many scripting languages out there especially taylored for use with C and C++ programs (like Lua) or powerful toolkits for binding your code to a separate scripting language (like Boost::Python).

The tool called SWIG falls into the later category, but is much more powerful than anything I have seen before. Not only it produces the needed wrapper classes automatically, it has also support for 13(!) scripting languages. So processing your header files with SWIG enables you (or the users of your library/application) to use your work with 13 different languages at a finger-snip! (And of course, no one is holding you back to sell each language-binding separately...)

The only question left open might be what scripting is good for. Scripting allows end-users to interact with your program in an easy and convenient way and offers the complete power of a mature language at the same time. Many games use scripting languages in order to control the game logic, most operating systems use scripts (shell-scripts or .BAT files) for doing small jobs. Scripting simply opens a huge door for your developers and even for your customers to use your program in many new ways you never though of. John Ousterhout (creator of Tcl) also has written a paper that describes the benefits of scripting languages.

RTTI and Reflection for C++

Posted by Kaya Kupferschmidt • Wednesday, March 15. 2006 • Category: C++
One important and useful feature is missing in C++: Reflection. Reflection is the ability of a language to acquire information about objects at runtime. Of course C++ has a typeid operator, but the use of the returned type_info is very limited and compiler dependant. What one is actually seeking for is complete information not only about class inheritance but also about all members and methods of each class.

Exactly this king of information offers the Reflex library developed at CERN. You can get all kinds of information about every object and class in your system, you can even instanciate new objects at runtime using string-literals describing a class and invoke any method of an object. One special advantage of this package is that it works in an absoultely non-intrusive manner, meaning that you do no have to change a single line of your code in order to get reflection. Instead of changing your code, Reflex relies on the gccxml parser that generates rich XML information about your classes. This information is then automatically transformed into some additional files containing cpp code containing all neccessary dictionaries and bindings to your code to enable full reflection.

Imagine the possibilities of such a system: You can easily integrate a scripting language into your program in a very generic manner if you use the rflection information provided by the Reflex library. WIth some additional work it should also be possible to serialise your objects to disk for providing persistent storage semantics. It even should be possible to implement some remote procedure calls building upon the reflection information provided by Reflex.

A Simple Sidebar