Undefined symbols error in root dictionary made with rootcint

Hi rooters,

This post is related to this recent discussion about wrapping a c++ class for python using rootcint. I am trying to do a more complicated implementation of the example done in the linked discussion, and running into some issues. I am easily able to wrap a simple c++ class using the method in the link, but things fell apart when I tried to use some non-standard c++ objects in the class. In particular, I cannot use the RAT toolkit, which is a c++ wrapper for GEANT4. If I leave out the lines of code that use RAT, the method below works fine, but if I include them, I get an unidentified symbol error. As a disclaimer, I am new to this type of thing, so I may missing something obvious. Here is a simplified version of what I am doing: I have a class AnalysisManager…

# include "TFile.h"

class AnalysisManager{
		TFile* f;
		AnalysisManager() {}
		virtual void func(TFile* f);


# include "AnalysisManager.h"
# include "TFile.h"
# include <RAT/DS/Root.hh>

void AnalysisManager::func(TFile* f) { 
	f->ls(); // does some stuff with the file
	RAT::DS::Root* r = new RAT::DS::Root(); // this causes the unidentified symbol error
	delete r;

I have a file called AnalysisManagerLinkDef.h which rootcint can use to make a root dictionary. AnalysisManagerLinkDef.h:

#ifdef __MAKECINT__
#pragma link C++ class AnalysisManager+;

With these three files, I can use rootcint to make the dictionary (analysismanagerdict.cxx) and compile it and the AnalysisManager.cc file into a shared library called libanalysismanager.so:

$ rootcint -f analysismanagerdict.cxx -c AnalysisManager.h AnalysisManagerLinkDef.h
$ g++ -I$ROOTSYS/include -c -fpic analysismanagerdict.cxx -o ./analysismanagerdict.o
$ g++ -I$ROOTSYS/include -I$RATROOT/include -L$RATROOT/lib -lrat -c -fpic AnalysisManager.cc -o ./AnalysisManager.o
$ g++ -shared -fpic AnalysisManager.o analysismanagerdict.o -o ./libanalysismanager.so

Then I can use the c++ object in python with

from ctypes import *
import ROOT as rt

lib = cdll.LoadLibrary('./libanalysismanager.so')
am = rt.AnalysisManager()
f = rt.Tfile("myfile.root", "RECREATE")

This works flawlessly if the line using RAT in AnalysisManager.cc is commented out (and the delete). However, with that line included, I get the following error:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    lib = cdll.LoadLibrary('./libanalysismanager.so')
  File "/usr/lib/python2.7/ctypes/__init__.py", line 440, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 362, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./libanalysismanager.so: undefined symbol: _ZTVN3RAT2DS4RootE

It may be that I have misunderstood the uses of rootcint, but it would be great to get this working if not! Please let me know your thoughts.


ROOT Version: 5.34/07
Platform: Ubuntu 16.04.6
Compiler: g++ 49.3-13ubuntu2

You need to either load the ‘RAT toolkit library’ on the python prompt or (better) add them to the shared library link line.


Hi @pcanal,

Sorry for the lack of follow up on my end, I keep having to put this on the back burner.

I updated the compilation process so I link the RAT toolkit in the shared library with no success. Is there anything obvious about my compilation process that is causing me issues?

rootcint -f analysismanagerdict.cxx -c AnalysisManager.h AnalysisManagerLinkDef.h
g++ -I$ROOTSYS/include -c -fpic analysismanagerdict.cxx -o ./analysismanagerdict.o
g++ -I$ROOTSYS/include -I$RATROOT/include -c -fpic AnalysisManager.cc -o ./AnalysisManager.o
g++ -I$ROOTSYS/include -I$RATROOT/include -L$RATROOT/lib -shared -fpic AnalysisManager.o analysismanagerdict.o -o ./libanalysismanager.so -lrat

Thanks again for the continued help.


What does ldd libanalysismanager.so prints?
What does nm -A libanalysismanager.so | grep _ZTVN3RAT2DS4RootE prints?
What does nm -A $RATROOT/lib/librat.so | grep _ZTVN3RAT2DS4RootE prints?

Hi Philippe,


linux-vdso.so.1 =>  (0x00007ffedbd76000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9bfb19b000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9bfae8b000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9bfac73000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9bfa8a3000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f9bfbaeb000)

After the above changes to the compilation process, the error I get lists a different symbol as the culprit: _ZN12TMatrixTBaseIdE4DrawEPKc.
When I check _ZTVN3RAT2DS4RootE it seems to be a weak symbol:


libanalysismanager.so:00000000005aad80 V _ZTVN3RAT2DS4RootE

I did just realize that the rat library Im trying to link is a static library (librat.a) which maybe changes things?


/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:Gsim.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InMicroCLEANProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:DSWriter.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InROOTProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:OutNetProc.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:OutROOTProc.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InDCDAQProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InAvalancheProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InFlatProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InDEAP1Producer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:DSReader.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:InNetProducer.o:                 U _ZTVN3RAT2DS4RootE
/data/snoplus/home/jschrott/.opt/rat/rat-vuv/lib/librat.a:RAT_Dict_jailbreak.o:0000000000000000 V _ZTVN3RAT2DS4RootE

Analogous commands for the _ZN12TMatrixTBaseIdE4DrawEPKc symbol show that it is undefined in both librat.a and libanalysismanager.so (only "U"s). Does this mean this is just a ROOT symbol?

Sorry for the massive dump of output!


So the include of the RAT library works and you now need to add the necessary ROOT library. Here that is -lMatrix.


1 Like

Adding -L$ROOTSYS/lib and -lMatrix made another undefined symbol error pop up (_ZTV9TRotation).

I then tried to link all the libraries in ROOT and RAT by replaceing the -l arguments with

$ROOTSYS/lib/*.a $ROOTSYS/lib/*.so $RATROOT/lib/*.a $RATROOT/lib/*.so

This produced yet another undefined symbol error (BZ2_bzread). I don’t know where this symbol could be coming from if not from RAT or ROOT. Any thoughts? I also tried loading all the ROOT libraries using root-config --glibs and root-config --libs


You need to add “-lPhysics -lMatrix”:

[...]$ c++filt _ZTV9TRotation
[...]$ grep TRotation ${ROOTSYS}/lib/*.rootmap

Don’t do that :slight_smile: :slight_smile:

Just add the one you need ( -lPhysics in this case)

Haha roger that! Ok this brings us to the last mystery: I’ve linked -lrat -lMatrix -lPhysics. Now I get an undefined symbol error for BZ2_bzread. Using the same tricks as before:

$ nm -A libanalysismanager.so | grep BZ2_bzread
libanalysismanager.so:                 U BZ2_bzread
$ nm -A $RATROOT/lib/librat.a | grep BZ2_bzread
$RATROOT/lib/librat.a:ReadFile.o:                 U BZ2_bzread

So BZ2_bzread is a referenced but undefined symbol in librat.a. It is not anywhere in ROOT though:

$ nm -A $ROOTSYS/lib/* | grep BZ2_bzread
--nothing-- #except errors about unrecognized rootmap files of course


$ c++filt BZ2_bzread
$ grep BZ2_bzread ${ROOTSYS}/lib/*.rootmap

I was thinking that BZ2_bzread might be a symbols from GEANT4 which I cant unmangle it because maybe GEANT4 was compiled with a different compiler (RAT is a wrapper for GEANT4 as a reminder). So I tried the following, but also got nothing.

$ nm -A <MyGEANT4>/lib/* | grep BZ2_bzread


Google says its from -lbz2

Success! I was stuck in rat-land for so long, I forgot something might actually come from another standard lib. The final list of required libraries was -lrat -lMatrix -lPhysics -lThread -lHist -lbz2. Thank you @pcanal for all the help! Not sure which reply to mark as the solution, but the case is definitely closed.


This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.