You are here

How to Use Reflex?

Purpose

Reflex stores and handles reflection information (types, members, etc). It is written in C++. Its reflection catalog can be queried by a small set of simple API classes. See the chapter Accessing Reflex Data. Unlike many other languages, C++ does not offer a way to determine which functions and data members are available for a certain class, or to call functions given their name, or to determine the memory offset of a data member given its name. Reflex adds all of that: it adds a type description layer on top of C++. It is non-intrusive: you do not have to change your types to use it. Generating Reflection Data

The database is usually populated with information extracted from C++ headers. Several tools, e.g. GCCXML / genreflex and CINT, can parse header files and extract reflection information, which gets then written as C++ sources (dictionaries) that can be compiled, linked, and loaded to make the data available to Reflex. See Generating Reflex Dictionaries for further info. Querying Reflection Data

Reflex features an interface that is amazingly clear when considering the complexity of C++. It only has a few classes that allow to query the database, insert new data dynamically, generate objects of available types, and invoke their methods.

There are a few examples of how to use Reflex. And of course we have an Reflex Online Class Reference.

Download

You can download the latest Reflex version here (320kB).

Building

Reflex uses a CMake based build system. It is expected to work on all known Linux flavors of the universe, on Windows with Microsoft Visual C++ >= 7.1 (aka 2003), on MacOS >= 10.4, and on Solaris. Your mileage may vary with other OSes; patches adding support for new platforms are always welcome.

Status

Reflex is used to store terabytes of data, it will be used by LHCb, CMS and Atlas to store petabyes of data. That probably qualifies for the attribute "mature". There are several users outside of ROOT, even outside of CERN - and even outside of High Energy Physics! One could say that Reflex is a part of High Energy Physics' contribution to society.

New Features

The addition of new features is driven by outside contributions. New features include annotations by Philippe Bourgau, Murex.

Support

As is obvious in such a context, Reflex is of course well supported (at least we try our best!). Bug reports should be submitted via Savannah, select "CINT" as the category. If you need human help you can post to the ROOT Forum and as the last resort (please!) you can send an email to rootdev@cern.ch or to axel@cern.ch.

Test Suite

Reflex has its own test suite. It is also based on CMake, and integrates nicely with Reflex's build system. It is pretty versatile - you might want to extract it and use it for your own projects! Check its license if you care about reusing it. And say "Thanks!" to Hady for creating it!

Contributions

We have a few of the current developers:

  • Axel Naumann at CERN,
  • Hady Zalek at Murex,
  • Philippe Bourgau at Murex, and
  • Philippe Canal at Fermilab.

That list is rather short, and these people are working on Reflex anywhere between 30% and 5% of their time. So we don't get everything done ourselves: we really appreciate contributions, feedback, ideas and discussions!

History

Reflex was developed at CERN starting around 2003. In 2007, Axel inherited it from Stefan Roiser, one of the main authors, who was responsible for it for several years, together with Pere Mato.

Alternatives

We are happy to list some of the alternative implementations - you just make your choice yourself :-) Google claims that these try to do the same:

  • XCppRefl
  • Hmm there was also cppreflect but SourceForge claims that it is not active anymore...

Right, so that was it. Let me know if I overlooked your package so I can add it!

Examples

Have a look to this page for some examples: http://seal-reflex.web.cern.ch/seal-reflex/examples.html

Generating Reflex Dictionaries

Selecting Types And Members

You can use selection files to tell genreflex what it should generate a dictionary for. If you do not use it, it will generate a dictionary for all types in the files passed at the command line, or when specifying --deep for all types it finds. The selection file is passed to genreflex with the -s parameters like this: genreflex -s selection.xml header1.h header2.h. It is an XML file with the following structure:

<lcgdict>
[<selection>]
  <class [name="classname"] [pattern="wildname"] 
         [file_name="filename"] [file_pattern="wildname"] 
         [id="xxxx"] [type="vector"]/>
  <class name="classname" >
    <field name="m_transient" transient="true"/>
    <field name="m_anothertransient" transient="true"/>
    <properties prop1="value1" [prop2="value2"]/>
  </class>
  <function [name="funcname"] [pattern="wildname"]
            [proto_name="name(int)"] [proto_pattern="name(int,*)"] />
  <enum [name="enumname"] [patter="wildname"] />
  <variable [name="varname"] [patter="wildname"] />
[</selection>]
<exclusion>
  <class [name="classname"] [pattern="wildname"] />
    <method name="unwanted" />
  </class>
...
</lcgdict>

Genreflex and Templates

The program parsing the header files and providing genreflex with the information what's in them is called GCCXML. It only sees templates if they are instantiated. See the C++ standard on when template instantiation happens. The rule of thumb is: if you design a templated class then it probably does not happen in that templated class's header! So you need to help GCCXML. There are two common approaches: the struct member, and the "proper" C++ way.

Explicit Template Instantiation

This is the preferred method, but it is not widely used. Suppose you have a templated template class C and a templated function template T A::f(const T&) const;. You can instantiate them (say with template parameter long long) using

#ifdef __GCCXML__
// GCCXML explicit template instantiation block
template class C<long long>;
template long long A::f<long long>(const long long&);
#endif

You can even put this into your regular header file: it is surrounded by an #ifdef __GCCXML__ and will thus be invisible to any other compiler. Template Instantiation By struct Members Suppose you have a templated template class C and a templated function template T f(const T&) const; defined in file C.h. You cannot instantiate the templated member function (at least I haven't found a way - do you know one?). For the templated class you can use:

#include "C.h"
#ifdef __GCCXML__
// GCCXML explicit template instantiation block
namespace {
  struct GCCXML_DUMMY_INSTANTIATION {
    C<long long> dummyMember;
  };
}
#endif

Often people put these instantiations into a separate header which in turn #includes the actual header, such that the C++ sources do not see the GCCXML_DUMMY_INSTANTIATION.