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…
AnalysisManager.h:
# include "TFile.h"
class AnalysisManager{
public:
TFile* f;
AnalysisManager() {}
virtual void func(TFile* f);
};
AnalysisManager.cc:
# 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+;
#endif
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")
am.func(f)
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.
-JSS
ROOT Version: 5.34/07
Platform: Ubuntu 16.04.6
Compiler: g++ 49.3-13ubuntu2