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+
Generating a dictionary by hand
ROOT's dictionary generator is called rootcint. You invoke it asrootcint -f DictOutput.cxx -c OPTIONS Header1.h Header2.h ... Linkdef.h
DictOutput.cxxspecifies the output file that will contain the dictionary. It will be accompanied by a header fileDictOutput.h.- OPTIONS can be simply skipped. Or it can be
-Isomethingto add an include path, i.e. to help rootcint find files included in Header1.h, Header2.h, etc.-pto invoke your compiler's preprocessor - which is usually better but slower than CINT's internal one-DSOMETHINGwill 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 __ */
#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 $^