Undefined reference loading shlib with custom class

Hi,

I’m trying to make a shlib for custom classes so that i can use them in ROOT, but i’m having trouble loading up the shlib:

I get the following error

dlopen error: /home/ataffard/MyWork/AtlasOffline-Any/UCINtuple_devel05_rel15.4.0/lib/libAnaUtils.so: undefined symbol: _ZTV9NtAnaBase Load Error: Failed to load Dynamic link library /home/ataffard/MyWork/AtlasOffline-Any/UCINtuple_devel05_rel15.4.0/lib/libAnaUtils.so

I’m compiling the classes via rootcint using a dictionary.

I’ve tried both linking all the lib that i can think of and making a .rootmap file without luck.

The problem is only NtAnaBase, since if i remove that from the dictionary just leaving TGuiUtils, I can load the lib just fine.

Any suggestions as to what i could possibly be missing…

Cheers
-a

Compilation output:

L/Atlas/AthenaSoft/sw/lcg/app/releases/ROOT/5.22.00d/slc4_ia32_gcc34/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic -O -m32 -lm /home/ataffard/MyWork/AtlasOffline-Any/UCINtuple_devel05_rel15.4.0/InstallArea/i686-slc4-gcc34-opt/lib/libNtuple.so -shared -O -Wall -fPIC -pthread -m32 -I/Atlas/AthenaSoft/sw/lcg/app/releases/ROOT/5.22.00d/slc4_ia32_gcc34/root/include -I/home/ataffard/MyWork/AtlasOffline-Any/UCINtuple_devel05_rel15.4.0/InstallArea/include/Ntuple/Ntuple:/home/ataffard/MyWork/AtlasOffline-Any/UCINtuple_devel05_rel15.4.0/UCIAnaCommon/AnaUtils/AnaUtils AnaUtilsDict.cxx -o libAnaUtils.so

Here’s what i have in the Makefile.

[code]ROOTCONFIG := root-config
ROOTCFLAGS := $(shell $(ROOTCONFIG) --cflags)
ROOTLDFLAGS := $(shell $(ROOTCONFIG) --ldflags)
ROOTLIBS := $(shell $(ROOTCONFIG) --libs)
ROOTGLIBS := $(shell $(ROOTCONFIG) --glibs)
HASTHREAD := $(shell $(ROOTCONFIG) --has-thread)

CXX = g++
CXXFLAGS = -O -Wall -fPIC $(ROOTCFLAGS) -I$(INCLUDE_DIR)
LD = g++
LDFLAGS = $(ROOTLIBS) -O $(ROOTLDFLAGS) -lm ${UCINTUPLE_DIR}/i686-slc4-gcc34-opt/lib/libNtuple.so
SOFLAGS = -shared

LIBS = $(ROOTLIBS) $(SYSLIBS)

GLIBS = $(ROOTGLIBS) $(SYSLIBS)

HDR = …/AnaUtils

LIB = libAnaUtils.so

$(LIB) : $(HDR)/AnaUtilsLinkDef.h
@rootcint -v3 -f AnaUtilsDict.cxx -c -I$(HDR) -I$(INCLUDE_DIR) -DDebug $(HDR)/NtAnaBase.h $(HDR)/AnaUtilsLinkDef.h
$(CXX) $(LDFLAGS) $(SOFLAGS) $(CXXFLAGS) AnaUtilsDict.cxx -o $@

@rm -f AnaUtilsDict.cxx AnaUtilsDict.h

@rlibmap -o libAnaUtils.rootmap -l libAnaUtils.so -d libNtuple.so  -c ../AnaUtils/AnaUtilsLinkDef.h
@ln -sf ../UCIAnaCommon/AnaUtils/run/libAnaUtils.so $(UCIANA_LIB)/
@ln -sf ../UCIAnaCommon/AnaUtils/run/libAnaUtils.rootmap $(UCIANA_LIB)/

clean:; @rm -f $(LIB) libAnaUtils.rootmap AnaUtilsDict.cxx AnaUtilsDict.h core [/code]

Header of NtAnaBase.h

[code]#ifndef NTANABASE_H
#define NTANABASE_H

#include
#include
#include
#include

#include <TROOT.h>

#include “…/…/…/UCINtuple/Ntuple/Ntuple/NtupleInterface.h”
//#include “NtupleInterface.h”
#include “TGuiUtils.h”

class TStopwatch;

using namespace std;

class NtAnaBase : public NtupleInterface, public TGuiUtils

[/code]

Hi,

echo _ZTV9NtAnaBase | c++filt vtable for NtAnaBaseSo you probably forgot to implement either the destructor or the first virtual function of NtAnaBase.

Cheers,
Philippe.

I get a similar error:

dlopen error: /home/.../CppTools/lib/libmylib.so: undefined symbol: _ZN8CppTools14DefinitionsCSCC1Ev

As you suggested I defined the destructor (I had forgot it), and when I type the command you suggested I get this:

echo _ZN8CppTools14DefinitionsCSCC1Ev | c++filt
CppTools::DefinitionsCSC::DefinitionsCSC()

What does it mean?

Actually my Definitions class is defined like this:

#ifndef DEFINITIONS_H
#define DEFINITIONS_H

#include "SelectionTools.h"


namespace CppTools
{

	class DefinitionsCSC {

		public:
			DefinitionsCSC(); //constructror
			virtual ~DefinitionsCSC(); //destructor

//		private:

			//muon object
			CppTools::MuonCuts muon;

			//electron objects
			CppTools::ElectronCuts elTight;
			CppTools::ElectronCuts elMed;
			CppTools::ElectronCuts elMedNoIso;
			CppTools::ElectronCuts elLoose;
			CppTools::ElectronCuts electron; //electron object used in analysis code

			//jet object
			CppTools::JetCuts jet;

			//truth jet object
			CppTools::JetCuts truth_jet;

			// SpclMc container cuts
			CppTools::TruthCuts truth;

                        //better to use a separate class for photons
			CppTools::PhotonCuts photon;

			//tau object
			CppTools::TauCuts tau;

			//! ROOT Dict ClassDef declaration
			ClassDef(DefinitionsCSC, 1)

	}; //end of Definitions class

} //End of the CppTools namespace


#endif // DEFINITIONS_H

Thanks a lot for any help,

Have a nice evening,

Ric.

Hi,

It means that you did not implement (or did not compile) the implementation for the default constructor.

Cheers,
Philippe.

Hi Philppe, thanks for your answer,

actually I have the implementation of the constructor inside the .cxx file, below:

#include "Definitions.h"
#include "SelectionTools.h"
#include "SystemOfUnits.h"

using namespace Gaudi::Units;

//Constructor
CppTools::DefinitionsCSC::DefinitionsCSC() {

    // Objects selection and overlap-removal cuts

        // Define muon
        muon.ptMin          = 0*GeV;
        muon.etaMax         = 2.5;
        muon.useEtCone      = true;
        muon.etConeMax      = 10*GeV;
        muon.deltaRVeto_mj  = 0.4; // veto muon if within a cone of 0.4 from a jet
        muon.applyOnlyAcceptanceCuts = true;
        muon.applyOverlapRemoval = true; // by default switch on overlap removal

       // ...etc etc...
}

I did a fresh make clean and then make again, and then I generate the dict again. I do not get errors during the compilation, but I have problem when loading the dict.

Actually I’m trying both moethods: rootcint and genreflex.

with rootcint I get no errors loading the .so lib, but then I cannot find my classes inside, as they are not generated fine. Actually I get a “lookup” error like this:

>>> import ROOT
>>> import PyCintex
>>> PyCintex.Cintex.Enable()
>>> PyCintex.loadDictionary("libDelphesCppToolsROOTCintDict")
>>> ROOT.CppTools
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00d/slc4_ia32_gcc34/root/lib/ROOT.py", line 372, in __getattr1
   return getattr( self, name )
 File "/afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00d/slc4_ia32_gcc34/root/lib/ROOT.py", line 394, in __getattr2
   attr = _root.LookupRootEntity( name )
AttributeError: CppTools 

while if I use genreflex I get an “undefined symbol” error, as I explained in another post here some minutes ago.

I’m sure I’m missing something… Might you help me?

Thanks again, and nice evening,

Ric.

Hi,

Is your .cxx compiled and linked and loaded as part of any shared library? Otherwise this is the issue.

Cheers,
Philippe.

Hi Philippe,

Mmmm…actually I’m not sure…

…maybe not!!!

I do not need any executable, but I have a lib.so from my package, generated with:

$(ANALIB): $(OBJS) Makefile
	$(LD) $(SOFLAGS) $(OBJS) $(OutPutOpt) $(ANALIB)

and then I generate and compile the dict with rootcint (or genreflex). But actually I do not pass any .cxx or the lib.so to the dict generation/compilation…

…so I think you are right, this is the problem.

Might I ask you how to “attach” the .cxx or the compiled lib.so to the dict compilation?

Thanks again,

Ric.

Thanks Philippe,

your suggestion worked!!

I just attached

to the dict lib compilation and it worked.
Now I can load the lib into Cint or PyROOT without errors due to “undefined symbols” anymore! :slight_smile:

…but I still have the “Lookup” Error when I try to call my objects.

All my classes and functions are defined in the same “CppTools” namespace, spread over several files.

When I try to access the namespace I have this error:

>>> import ROOT
>>> import PyCintex
>>> PyCintex.Cintex.Enable()
>>> PyCintex.loadDictionary("libmylib")
>>> ROOT.CppTools
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/afs/cern.ch/sw/lcg/app/releases/ROOT/5.22.00d/slc4_ia32_gcc34/root/lib/ROOT.py", line 394, in __getattr2
    attr = _root.LookupRootEntity( name )
AttributeError: CppTools
>>>

With genreflex, in order to generate the dict I use this selection.xml file:

<lcgdict>
  <function pattern="CppTools::*" />
  
  
  <class name="CppTools::DefinitionsCSC" />
  <class name="CppTools::ElectronCuts" />  
  <class name="CppTools::PhotonCuts" />  
  <class name="CppTools::MuonCuts" />  
  <class name="CppTools::JetCuts" />
  <class name="CppTools::TauCuts" />  
  <class name="CppTools::TruthCuts" />  
  <class name="CppTools::LeptonsProps" />  
  <class name="CppTools::PhotonsProps" />  
  <class name="CppTools::SortByPtValDesc" />  
  <class name="CppTools::SortByPtValDescPh" />
  

  

</lcgdict>

and I run it with this command:

genreflex DelphesWatchManDict.h --deep -s selection.xml -o LCGdict.cc -I $ROOTSYS/include

--->> genreflex: INFO: Parsing file DelphesWatchManDict.h with GCC_XML OK
--->> genreflex: INFO: Generating Reflex Dictionary
class CppTools::LeptonsProps
class CppTools::DefinitionsCSC
class CppTools::JetCuts
class CppTools::TauCuts
class CppTools::PhotonCuts
class CppTools::MuonCuts
class CppTools::PhotonsProps
class CppTools::ElectronCuts
class CppTools::SortByPtValDesc
class CppTools::SortByPtValDescPh
class CppTools::TruthCuts
function CppTools::TransverseMass(double, double, double)
function CppTools::IsVetoed(TRootPhoton const&, TRootJet const&, CppTools::PhotonCuts const&)
function CppTools::IsVetoed(TRootMuon const&, TRootJet const&, CppTools::MuonCuts const&)
function CppTools::IsVetoed(TRootElectron const&, TRootJet const&, CppTools::ElectronCuts const&)
function CppTools::IsSelected(TRootTauJet const&, CppTools::TauCuts const&)
function CppTools::IsSelected(TRootJet const&, CppTools::JetCuts const&)
function CppTools::IsSelected(TRootMuon const&, CppTools::MuonCuts const&)
function CppTools::IsSelected(TRootPhoton const&, CppTools::PhotonCuts const&)
function CppTools::IsSelected(TRootElectron const&, CppTools::ElectronCuts const&)
function CppTools::Sphericity(std::vector<float, std::allocator<float> >&, std::vector<float, std::allocator<float> >&, std::vector<float, std::allocator<float> >&, bool)
function CppTools::IsOverlapping(TRootMuon const&, TRootTauJet const&, CppTools::TauCuts const&)
function CppTools::IsOverlapping(TRootElectron const&, TRootTauJet const&, CppTools::TauCuts const&)
function CppTools::IsOverlapping(TRootJet const&, TRootTauJet const&, CppTools::TauCuts const&)
function CppTools::IsOverlapping(TRootJet const&, TRootPhoton const&, CppTools::PhotonCuts const&)
function CppTools::IsOverlapping(TRootJet const&, TRootElectron const&, CppTools::ElectronCuts const&)
function CppTools::GetFourVector(TRootParticle const&)

And then I compile it with this line:

g++ DelphesWatchManDict.h LCGdict.cc -o libmylib.so  `root-config --cflags --libs`  -lReflex -lCintex -shared -L$PWD/../lib -lDelphesCppTools -lUtilities

I’m sure I’m missing other trivial things here… :->

Thanks again for your kind help, Philippe,

Ric.

p.s.

I get the same “lookup error” if I use rootcint, instead of genreflex, using this LinkDef.h file:


#include "SelectionTools.h"
#include "Definitions.h"
#include "Variables.h"

#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ nestedtypedefs;
#pragma link C++ nestedclasses;

#pragma link C++ namespace CppTools;

#pragma link C++ global CppTools;

#pragma link C++ class CppTools;
#pragma link C++ class CppTools::ElectronCuts;
#pragma link C++ class CppTools::PhotonCuts;
#pragma link C++ class CppTools::MuonCuts;
#pragma link C++ class CppTools::JetCuts;
#pragma link C++ class CppTools::TruthCuts;
#pragma link C++ class CppTools::TauCuts;
#pragma link C++ class CppTools::LeptonsProps;
#pragma link C++ class CppTools::PhotonsProps;
#pragma link C++ class CppTools::SortByPtValDesc;
#pragma link C++ class CppTools::SortByPtValDescPh;
#pragma link C++ class CppTools::DefinitionsCSC;

#endif

Ric.

Hi Philippe,

thanks to your suggestions I found the error: as you told, it was a linking problem again!!

So now it works perfectly, I can access all my objects from PyROOT:

>>> import ROOT
>>> import PyCintex
>>> PyCintex.Cintex.Enable()
>>> PyCintex.loadDictionary("libDelphesCppToolsROOTGenreflexDict")
>>> ROOT.CppTools
<class 'ROOT.CppTools'>
>>> ROOT.CppTools.JetCuts
<class '__main__.CppTools::JetCuts'>
>>> ROOT.CppTools.JetCuts.StandardJetCuts
<ROOT.MethodProxy object at 0xb7eacf2c>
>>>   

Actually I did not link the .so lib generated from my code, while compiling the .so from the Genreflex dict generation.

Thanks again Philippe for your help, kind as usual! :slight_smile:

Best regards,

Ric.