Interacting with Shared Libraries: rootcint

Not only can CINT interpret C++, it can also call functions inside libraries! But it needs a bit of help: the dictionary. These dictionaries are also needed to write a class to a ROOT file.

Dictionaries

A dictionary ("reflection database") contains information about the types and functions that are available in a library. Most LHC experiments use Reflex for that - here we will focus on the CINT / rootcint way, which is a lot easier to handle when working with ROOT.

ROOT's dictionary consists of a source file which contains the type information needed by CINT. This source file needs to be generated from the library's headers and then compiled, linked and loaded - only then does CINT know what's inside a library.

Using ACLiC to generate dictionaries

ROOT can automatically generate dictionaries for you, given a header file. For that just run

.L MyHeader.h+
As explained in more details in the CINT prompt web page, the "+" at the end (ACLiC) invokes the dictionary generator and all the rest.

Generating a dictionary by hand

ROOT's dictionary generator is called rootcint. You invoke it as
rootcint -f DictOutput.cxx -c OPTIONS Header1.h Header2.h ... Linkdef.h
Let's look at the different parts:
  • DictOutput.cxx specifies the output file that will contain the dictionary. It will be accompanied by a header file DictOutput.h.
  • OPTIONS can be simply skipped. Or it can be
    • -Isomething to add an include path, i.e. to help rootcint find files included in Header1.h, Header2.h, etc.
    • -p to invoke your compiler's preprocessor - which is usually better but slower than CINT's internal one
    • -DSOMETHING will define a preprocessor macro which is sometimes needed to parse header file.
  • Header1.h Header2.h... are the headers that rootcint will read and extract the type information from.
  • Linkdef.h is the magic file that steers rootcint; it's worth its own page!

Hiding code from rootcint

Sometimes CINT doesn't manage to parse a library's header file. You have two options: extract the relevant parts into a separate header that you then compile with ".L ...+", or hide the parts that CINT cannot parse by surrounding them with

#ifndef __CINT__
complex code
#endif /* __CINT __ */

or (for example this is useful if you use the boost header files):
#ifndef __CINT__
#include <complex_header.h>
#else
class complex_class;
#endif /* __CINT __ */

Embedding the rootcint call into a GNU Makefile

Using .L MyCode.C+ to compile and run code is the simplest option If you really need to use a Makefile, here is a rule for generating a dictionary. It will create a new source file which you should compile and like like all the other sources in your library. Of course you will need to add the include path for ROOT, and you might have to link against ROOT's libraries libCore libCint.

This rule will generate the rootcint dictionary for the headers $(HEADERS) and a library containing the dictionary and the compiled $(SOURCES):

MyDict.cxx: $(HEADERS) Linkdef.h
[TAB]     rootcint -f $@ -c $(CXXFLAGS) -p $^
 
libMyLib.so: MyDict.cxx $(SOURCES)
[TAB]     g++ -shared -o$@ `root-config --ldflags` $(CXXFLAGS) -I$(ROOTSYS)/include $^