This is related to my work reading TTree data into Avro or the JVM. Currently, I require users to have a dynamic library with TDictionaries, e.g. Event_cxx.so and Event_cxx_ACLiC_dict_rdict.pcm. I’d like to relax that requirement because all of the class structure information is already in the ROOT file in the form of TStreamers (ignoring complications like CMSSW’s custom streamers).
I know how to generate a header file from the TStreamer info, and anyway if I required users to supply a C++ header file, at least a text file is a lot more platform-independent than dynamic libraries. Furthermore, I know that a header file with all its method definitions (or no methods) can be compiled by Cling with
.L fileName.h
or
gInterpreter->Declare(fileAsString);
both of which can be accessed programmatically. This loads the class to the degree that it can be referenced with
TClass::GetClass(className);
and while it doesn’t have a
TClass::GetClass(className)->GetTypeInfo()
that TTreeReaderValue requires to get a TDictionary, I can get the TDictionary with
TDictionary::GetDictionary(className)
and use that in a custom subclass of TTreeReaderValueBase. However, when ROOT actually tries to read data into that class, it encounters a “TClass::New: cannot create object of class” error. Here’s a full interactive session illustrating what I’m trying to do.
[code]root [0] .L test_Event/Event.h
root [1] TFile *f = TFile::Open(“test_Event/Event.root”)
(TFile ) 0x1c56530
root [2] TTreeReader r(“T”, f)
(TTreeReader &) Name: TTreeReader Title: A simple interface to read trees
root [3] TDictionary::GetDictionary(“Event”)
(TDictionary ) 0x1f6a440
root [4] class MyReader: public ROOT::Internal::TTreeReaderValueBase {
root (cont’ed, cancel with .@) [5]public:
root (cont’ed, cancel with .@) [6] MyReader(TTreeReader &r, const char branchname, const char classname) : TTreeReaderValueBase(&r, branchname, TDictionary::GetDictionary(classname)) { }
root (cont’ed, cancel with .@) [7] const char *GetDerivedTypeName() const { return “blah”; }
root (cont’ed, cancel with .@) [8]};
root [9] MyReader myreader(r, “event”, “Event”)
(MyReader &) @0x7f2c4cdd5108
root [10] r.Next()
(Bool_t) true
root [11] myreader.GetAddress()
Error in TClass::New: cannot create object of class Event
*** Break *** segmentation violation
Generating stack trace…
0x00007f2c3f874380 in ROOT::Detail::TBranchProxy::Setup() + 0xc90 from /opt/root_v6.06.00/lib/libTreePlayer.so
0x00007f2c3f84f0e7 in ROOT::Internal::TTreeReaderValueBase::ProxyRead() + 0x67 from /opt/root_v6.06.00/lib/libTreePlayer.so
0x00007f2c3f84f929 in ROOT::Internal::TTreeReaderValueBase::GetAddress() + 0x9 from /opt/root_v6.06.00/lib/libTreePlayer.so
0x00007f2c4cd9d035 in
0x00007f2c48de8b13 in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) + 0x1b3 from /opt/root_v6.06.00/lib/libCling.so
0x00007f2c48dee217 in cling::Interpreter::EvaluateInternal(std::basic_string<char, std::char_traits, std::allocator > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**) + 0x157 from /opt/root_v6.06.00/lib/libCling.so
0x00007f2c48dee353 in cling::Interpreter::process(std::basic_string<char, std::char_traits, std::allocator > const&, cling::Value*, cling::Transaction**) + 0x83 from /opt/root_v6.06.00/lib/libCling.so
0x00007f2c48e85c93 in cling::MetaProcessor::process(char const*, cling::Interpreter::CompilationResult&, cling::Value*) + 0x233 from /opt/root_v6.06.00/lib/libCling.so
0x00007f2c48d73736 in TCling::ProcessLine(char const*, TInterpreter::EErrorCode*) + 0x906 from /opt/root_v6.06.00/lib/libCling.so
0x00007f2c4c708eb0 in TApplication::ProcessLine(char const*, bool, int*) + 0x3b0 from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4cb5c1bf in TRint::ProcessLineNr(char const*, char const*, int*) + 0x9f from /opt/root_v6.06.00/lib/libRint.so
0x00007f2c4cb5c4d1 in TRint::HandleTermInput() + 0x221 from /opt/root_v6.06.00/lib/libRint.so
0x00007f2c4c7f17c5 in TUnixSystem::CheckDescriptors() + 0x155 from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4c7f275a in TUnixSystem::DispatchOneEvent(bool) + 0xca from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4c73b006 in TSystem::InnerLoop() + 0x16 from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4c73bc10 in TSystem::Run() + 0x70 from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4c70731f in TApplication::Run(bool) + 0x1f from /opt/root_v6.06.00/lib/libCore.so
0x00007f2c4cb5da38 in TRint::Run(bool) + 0x538 from /opt/root_v6.06.00/lib/libRint.so
0x00000000004010ac in main + 0x4c from /opt/root_v6.06.00/bin/root.exe
0x00007f2c4bc76ec5 in __libc_start_main + 0xf5 from /lib/x86_64-linux-gnu/libc.so.6
0x000000000040111a in from /opt/root_v6.06.00/bin/root.exe
[/code]
Any ideas? Is there a way to do this differently? Or is this a bug? (I’ve strayed far from the path of what a normal user might do, so I’m not sure if this is supposed to be undefined behavior or not.)
Thanks!