Utilities

The cppyy-backend package brings in the following utilities to help with repackaging and redistribution:

  • cling-config: for compile time flags

  • rootcling and genreflex: for dictionary generation

  • cppyy-generator: part of the CMake interface

Compiler/linker flags

cling-config is a small utility to provide access to the as-installed configuration, such as compiler/linker flags and installation directories, of other components. Usage examples:

$ cling-config --help
Usage: cling-config [--cflags] [--cppflags] [--cmake]
$ cling-config --cmake
/usr/local/lib/python2.7/dist-packages/cppyy_backend/cmake

Dictionaries

Loading header files or code directly into cling is fine for interactive work and smaller packages, but large scale applications benefit from pre-compiling code, using the automatic class loader, and packaging dependencies in so-called “dictionaries.”

A dictionary is a generated C++ source file containing references to the header locations used when building (and any additional locations provided), a set of forward declarations to reduce the need of loading header files, and a few I/O helper functions. The name “dictionary” is historic: before cling was used, it contained the complete generated C++ reflection information, whereas now that is derived at run-time from the header files. It is still possible to fully embed header files rather than only storing their names and search locations, to make the dictionary more self-contained.

After generating the dictionary, it should be compiled into a shared library. This provides additional dependency control: by linking it directly with any further libraries needed, you can use standard mechanisms such as rpath to locate those library dependencies. Alternatively, you can add the additional libraries to load to the mapping files of the class loader (see below).

Note

The JIT needs to resolve linker symbols in order to call them through generated wrappers. Thus, any classes, functions, and data that will be used in Python need to be exported. This is the default behavior on Mac and Linux, but not on Windows. On that platform, use __declspec(dllexport) to explicitly export the classes and function you expect to call. CMake has simple support for exporting all C++ symbols.

In tandem with any dictionary, a pre-compiled module (.pcm) file will be generated. C++ modules are still on track for inclusion in the C++20 standard and most modern C++ compilers, clang among them, already have implementations. The benefits for cppyy include faster bindings generation, lower memory footprint, and isolation from preprocessor macros and compiler flags. The use of modules is transparent, other than the requirement that they need to be co-located with the compiled dictionary shared library.

Optionally, the dictionary generation process also produces a mapping file, which lists the libraries needed to load C++ classes on request (for details, see the section on the class loader below).

Structurally, you could have a single dictionary for a project as a whole, but more likely a large project will have a pre-existing functional decomposition that can be followed, with a dictionary per functional unit.

Generation

There are two interfaces onto the same underlying dictionary generator: rootcling and genreflex. The reason for having two is historic and they are not complete duplicates, so one or the other may suit your preference better. It is foreseen that both will be replaced once C++ modules become more mainstream, as that will allow simplification and improved robustness.

rootcling

The first interface is called rootcling:

$ rootcling
Usage: rootcling [-v][-v0-4] [-f] [out.cxx] [opts] file1.h[+][-][!] file2.h[+][-][!] ...[Linkdef.h]
For more extensive help type: /usr/local/lib/python2.7/dist-packages/cppyy_backend/bin/rootcling -h

Rather than providing command line options, the main steering of rootcling behavior is done through #pragmas in a Linkdef.h file, with most pragmas dedicated to selecting/excluding (parts of) classes and functions. Additionally, the Linkdef.h file may contain preprocessor macros.

The output consists of a dictionary file (to be compiled into a shared library), a C++ module, and an optional mapping file, as described above.

genreflex

The second interface is called genreflex:

$ genreflex
Generates dictionary sources and related ROOT pcm starting from an header.
Usage: genreflex headerfile.h [opts] [preproc. opts]
...

genreflex has a richer command line interface than rootcling as can be seen from the full help message.

Selection/exclusion is driven through a selection file using an XML format that allows both exact and pattern matching to namespace, class, enum, function, and variable names.

Example

Consider the following basic example code, living in a header “MyClass.h”:

class MyClass {
public:
    MyClass(int i) : fInt(i) {}
    int get_int() { return fInt; }

private:
    int fInt;
};

and a corresponding “Linkdef.h” file, selecting only MyClass:

#ifdef __ROOTCLING__
#pragma link off all classes;
#pragma link off all functions;
#pragma link off all globals;
#pragma link off all typedef;

#pragma link C++ class MyClass;

#endif

For more pragmas, see the rootcling manual. E.g., a commonly useful pragma is one that selects all C++ entities that are declared in a specific header file:

#pragma link C++ defined_in "MyClass.h";

Next, use rootcling to generate the dictionary (here: MyClass_rflx.cxx) and module files:

$ rootcling -f MyClass_rflx.cxx MyClass.h Linkdef.h

Alternatively, define a “myclass_selection.xml” file:

<lcgdict>
    <class name="MyClass" />
</lcgdict>

serving the same purpose as the Linkdef.h file above (in fact, rootcling accepts a “selection.xml” file in lieu of a “Linkdef.h”). For more tags, see the selection file documentation. Commonly used are namespace, function, enum, or variable instead of the class tag, and pattern instead of name with wildcarding in the value string.

Next, use genreflex to generate the dictionary (here: MyClass_rflx.cxx) and module files:

$ genreflex MyClass.h --selection=myclass_selection.xml -o MyClass_rflx.cxx

From here, compile and link the generated dictionary file with the project and/or system specific options and libraries into a shared library, using cling-config for the relevant cppyy compiler/linker flags. (For work on MS Windows, this helper script may be useful.) To continue the example, assuming Linux:

$ g++ `cling-config --cppflags` -fPIC -O2 -shared MyClass_rflx.cxx -o MyClassDict.so

Instead of loading the header text into cling, you can now load the dictionary:

>>> import cppyy
>>> cppyy.load_reflection_info('MyClassDict')
>>> cppyy.gbl.MyClass(42)
<cppyy.gbl.MyClass object at 0x7ffb9f230950>
>>> print(_.get_int())
42
>>>

and use the selected C++ entities as if the header was loaded.

The dictionary shared library can be relocated, as long as it can be found by the dynamic loader (e.g. through LD_LIBRARY_PATH) and the header file is fully embedded or still accessible (e.g. through a path added to cppyy.add_include_path at run-time, or with -I to rootcling/genreflex during build time). When relocating the shared library, move the .pcm with it. Once support for C++ modules is fully fleshed out, access to the header file will no longer be needed.

Class loader

Explicitly loading dictionaries is fine if this is hidden under the hood of a Python package and thus transparently done on import. Otherwise, the automatic class loader is more convenient, as it allows direct use without having to manually find and load dictionaries (assuming these are locatable by the dynamic loader).

The class loader utilizes so-called rootmap files, which by convention should live alongside the dictionary shared library (and C++ module file). These are simple text files, which map C++ entities (such as classes) to the dictionaries and other libraries that need to be loaded for their use.

With genreflex, the mapping file can be automatically created with --rootmap-lib=MyClassDict, where “MyClassDict” is the name of the shared library (without the extension) build from the dictionary file. With rootcling, create the same mapping file with -rmf MyClassDict.rootmap -rml MyClassDict. It is necessary to provide the final library name explicitly, since it is only in the separate linking step where these names are fixed and those names may not match the default choice.

With the mapping file in place, the above example can be rerun without explicit loading of the dictionary:

>>> import cppyy
>>> from cppyy.gbl import MyClass
>>> MyClass(42).get_int()
42
>>>

Bindings collection

cppyy-generator is a clang-based utility program which takes a set of C++ header files and generates a JSON output file describing the objects found in them. This output is intended to support more convenient access to a set of cppyy-supported bindings:

$ cppyy-generator --help
usage: cppyy-generator [-h] [-v] [--flags FLAGS] [--libclang LIBCLANG]
                       output sources [sources ...]
...

This utility is mainly used as part of the CMake interface.