Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address


There are some posts about this that are similar but their solutions didn’t seem to work for me… I created a simple class, jet.h, and I’ve saved it into a ttree as an array of jet objects.

jet m_jets[Max_jet_size];
TTree * towerntuple = new TTree(“towerntup”, “Ntuple”);
towerntuple->Branch(“jets”,m_jets, 32000, 0);

and then I try to read it

jet jets[10000];
t->SetBranchAddress(“jets”,&jets);

And then I get my error
Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address for “jets”. The class expected (jet) does not have a dictionary and needs to be emulated for I/O purposes but is being passed a compiled object.Please generate the dictionary for this class (jet)

This class is already compiled, so I tried loading the library as
gSystem->Load(libjet.so)
but that didn’t do anything either.

The class is simple enough that I could technically break it up into a bunch of branches, but if there’s a solution here I’d like to know!

Thanks

ROOT Version: 6.28.04
Platform: Ubuntu 22.04
Compiler: gcc 11.3


As the error says, there is no dictionary for the jet class. So you should create one, using the proper Linkdef.h, containing something like:

#ifdef __CLING__
#pragma link C++ class jet+;
#endif

and using rootcling:

rootcling -f jetDict.cxx -c jet.h Linkdef.h

See also I/O of custom classes - ROOT

Hi, thanks for the quick reply. I have generated the jetDict.cxx and jetDict_rdict.pcm.

What is the syntax to actually load them for my script to use?

When I try to include the generated .cxx file, I get the following error
Error in <TCling::RegisterModule>: Dictionary trigger function for jetDict not found

Just add the jetDict.cxx as any other source file to your shared library. the jetDict_rdict.pcm. should be copied into the same directory as the shared library that contains the dictionary .o files.

1 Like

Alright we’re getting closer. Now the error only reads
Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address for “jets”. This is probably due to a missing dictionary, the original data class for this branch is jet.
the jetDict_rdict.pcm is in the same location as my libjet.so, and if I run
nm libjet.so | grep jetDict
I do see output indicating my dict is now in my shared library.
Is there anything extra I need to include in my macro or something?

There is 2 issues. The minor issue is that the SetBranchAddress is misleading. The larger issue is that the branch creation is unlikely to be doing what you were hoping for.

jet m_jets[Max_jet_size];
TTree * towerntuple = new TTree(“towerntup”, “Ntuple”);
towerntuple->Branch(“jets”,m_jets, 32000, 0);

only store a single jet (and not the Max_jet_size you may have wanted.

Consequently SetBranchAddress is expecting the address of a pointer to a single object. i.e.:

jet *single_jet = nullptr;
t->SetBranchAddress(“jets”,&single_jet);

will ‘work’.

jet jets[10000];
t->SetBranchAddress(“jets”,&jets);

compiles but fails at run-time because it can not find a dictionary for (jet[10000]) (Admittedly the error message could be improved).

You have three potential solution for this issues.

One is to use std::vector<jet> instead of the fixed size array (need a dictionary for the vector)

Another is to wrap the the array in a help struct;

struct jetArray {
   jet m_jets[Max_jet_size]; // or std::array<jet, Max_jet_size>
};

and store a jetArray in the branch (need a dictionary for jetArray).

Lastly, the notation m_jets hints that this is already a data member of a struct or class. And, especially you also need/want to store the other data member of that class, you could generate a dictionary for that class and store the whole class in the TTree/Branch instead of just one of its data member.

1 Like