Dear ROOT experts,
I am currently working on a Geant4 simulation program which links to ROOT, and I would like to store event information into a ROOT Tree using a custom Class as the data model. I think it is possible to do it without creating libraries / dictionaries such as it is shown here: Chapter: Trees, since I don’t need to implement any method in this class, it is only used as storage.
The tutorials (such this one I have linked) seem to be a bit outdated, providing many dead references. The best example I could find was ROOT: tutorials/tree/tree0.C File Reference. I have managed to run this successfuly on the ROOT console:
#include <TTree.h>
class Event : public TObject
{
public:
Int_t fEventID;
ClassDef(Event, 1)
};
ClassImp(Event);
void event()
{
TTree *tree = new TTree("tree", "My Tree");
Event *e = new Event;
tree->Branch("Event", &e);
Int_t nevent = 10000;
for (Int_t iev = 0; iev < nevent; iev++)
{
e->fEventID = iev;
tree->Fill();
}
tree->Show(0);
}
root [3] tree->Show(2)
======> EVENT:2
fEventID = (Event*)0x7ffe429cfa70
fUniqueID = 0
fBits = 50331648
fEventID = 2
However I am failing to achieve the same results in my standalone c++ program that links to ROOT. I would like to know the “canonical” way to achieve this, hopefully without having to create a library.
In my project I have:
// ... all dependencies ...
// DataModel.h
class UserGeant4Event : public TObject {
public:
Int_t fEventID;
public:
UserGeant4Event();
~UserGeant4Event();
ClassDef(UserGeant4Event, 1);
};
// DataModel.cpp
#include "DataModel.h"
ClassImp(UserGeant4Event);
UserGeant4Event::UserGeant4Event() {}
UserGeant4Event::~UserGeant4Event() {}
Currently its not compiling giving errors such as (sorry they are not in english):
/usr/bin/ld: CMakeFiles/restGeant4.dir/src/DataModel.cpp.o: en la función `__static_initialization_and_destruction_0(int, int)':
/tmp/tmp.HxEn9kcj7v/src/DataModel.cpp:4: referencia a `ROOT::GenerateInitInstance(UserGeant4Event const*)' sin definir
/usr/bin/ld: CMakeFiles/restGeant4.dir/src/DataModel.cpp.o: en la función `UserGeant4Event::IsA() const':
/tmp/tmp.HxEn9kcj7v/include/DataModel.h:73: referencia a `UserGeant4Event::Class()' sin definir
/usr/bin/ld: CMakeFiles/restGeant4.dir/src/DataModel.cpp.o: en la función `UserGeant4Event::ShowMembers(TMemberInspector&) const':
/tmp/tmp.HxEn9kcj7v/include/DataModel.h:73: referencia a `UserGeant4Event::Class()' sin definir
/usr/bin/ld: CMakeFiles/restGeant4.dir/src/DataModel.cpp.o:(.data.rel.ro._ZTV15UserGeant4Event[_ZTV15UserGeant4Event]+0x1e0): referencia a `UserGeant4Event::Streamer(TBuffer&)' sin definir
collect2: error: ld returned 1 exit status
Looks like its a linker issue, but no idea how to fix it.
Thanks in advance!
Edit:
If I remove ClassDef
and ClassImp
macro calls, the program will compile but the object stored in the TTree will be a plain TObject*
without the fields I defined.
All the remotely useful information I can find online is related to ROOT dictionaries (such as ROOT macros and shared libraries - ROOT), can’t I do what I intend without dictionaries? The ROOT macro doesn’t seem to use them, I can open the tree without loading any dictionaries
A “workaround” (maybe its the only way?) is to define a dictionary and link to the library, but it looks too involved for what I want to achieve (following GitHub - eguiraud/root_dictionaries_tutorial: A tutorial on creating ROOT dictionaries to perform I/O of custom C++ classes).
I have created a repository: GitHub - lobis/root_event_tree_cmake: A simple template to save a ROOT Class into a TTree to show my progress, hopefuly it can serve as a reference when (if) I manage to get it working.