Using rootcint to generate dictionaries for standalone progs

Hi,

I’m trying to read a stl collection of std::vector<std::vector >, unfortunately its proving difficult.

When I open my input file using root, I don’t get any errors about nested vectors, but when I try to use the following minimal example:
tree-bug.cxx:

#include "TFile.h"
#include "TTree.h"
#include <iostream>
#include <vector>
using namespace std;
int main(void){
  TFile file("ntuple.root");
  TTree* tree = dynamic_cast<TTree*>(file.Get("JPsi"));
  std::vector<std::vector<int> > *mu_trk_idx=NULL;
  tree->SetBranchAddress("MUONS_index",&mu_trk_idx);
  cout << tree << " "<< tree->GetName() << " "<< tree->GetEntries()<<endl;
  for(int i = 0; i < tree->GetEntries(); i++){
    tree->GetEntry(i);
  }
  return 0;
}

I get the following error:

Error in <TTree::SetBranchAddress>: Unable to determine the type given for the address for "MUONS_index". The class expected (vector<vector<int> >) refers to an stl collection and do not have a compiled CollectionProxy. Please generate the dictionary for this class (vector<vector<int> >) 0x143cca0 JPsi 23171

Here’s the rules from my Makefile:

src/dict.cxx: include/LinkDef.h
	rootcint -f $@ -c $(CXXFLAGS) -p $^
src/libDict.so: src/dict.cxx
	$(CC) -shared -fPIC -o$@ $(CXXFLAGS) $^
bin/tree-bug: bin/tree-bug.o src/libDict.so
	$(CC) $^ -o $@ $(LDFLAGS) -L ./src -l Dict

My LinkDef.h looks like:

#include <vector>
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;
#pragma link C++ std::vector<std::vector<int> >+;
#endif

I don’t understand what I’m doing wrong. I’ve read Chapter 15 of the Users Guide, and I didn’t find anything that I’m doing something wrong. To be absolutely explicit, here’s the list of commands that my Makefile simplifies to:

rootcint -f src/dict.cxx -c -m64 -pg -I/home/dave/tree-test/include -I/home/dave/root/include -I/home/dave/local/include -O0 -g3 -fno-inline  -Wextra -Wall  -ansi -p include/LinkDef.h
g++ -shared -fPIC -osrc/libDict.so -m64 -pg -I/home/dave/tree-test/include -I/home/dave/root/include -I/home/dave/local/include -O0 -g3 -fno-inline  -Wextra -Wall  -ansi src/dict.cxx
g++ bin/tree-bug.o src/libDict.so -o bin/tree-bug -L/home/dave/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic -Wl,-rpath,/home/dave/local/lib -lm -L/home/dave/local/lib -lfastjettools -lfastjet -lNsubjettiness  -L ./src -l Dict

Here’s my root version:

ROOT 5.34/26 (v5-34-26@v5-34-26, Feb 20 2015, 13:23:25 on linuxx8664gcc)

And if it matters my machine and gcc version:

$ uname -a
Linux XXXXXX 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3~deb8u1 (2015-04-24) x86_64 GNU/Linux
$ g++ --version
g++ (Debian 4.9.2-10) 4.9.2

[root.cern.ch/phpBB3/viewtopic.p … 570#p83570](Vector of vector in a tree - filling clone tree
[root.cern.ch/phpBB3/viewtopic.p … 491#p81491](Error in <TTree::Branch> - Vector issue

Thanks for the prompt response. I read the post you linked yesterday and I didn’t see the officially recommended solution using the loader.C file. I tried making the dictionary library with this method and it works. Now the question is why? As I understand the documentation, I’m doing it correctly with my approach. How do I dump the commands that root is using to call rootcint and ld?

Hi,

I suspect the problem in your case is that the linker decided that since there is no hard dependency on your dictionary library, it does not really need to link it. If that is the case when doingldd bin/tree-bug it would not appear.

Cheers,
Philippe.

PS. As a side note that a modern replacement for the loader.C technique is to use TInterpreter::GenerateDictionary.

I wish the documentation for how to do this was a little more clear, here’s the output of ldd using the Makefile rules:

ldd bin/tree-bug
	linux-vdso.so.1 (0x00007ffcd09db000)
	src/libDict.so (0x00007f719b727000)
	libCore.so => /home/dave/root/lib/libCore.so (0x00007f719adc7000)
	libCint.so => /home/dave/root/lib/libCint.so (0x00007f719a448000)
	libRIO.so => /home/dave/root/lib/libRIO.so (0x00007f7199f12000)
	libNet.so => /home/dave/root/lib/libNet.so (0x00007f7199bb3000)
	libHist.so => /home/dave/root/lib/libHist.so (0x00007f7199455000)
	libGraf.so => /home/dave/root/lib/libGraf.so (0x00007f719905a000)
	libGraf3d.so => /home/dave/root/lib/libGraf3d.so (0x00007f7198d45000)
	libGpad.so => /home/dave/root/lib/libGpad.so (0x00007f7198a44000)
	libTree.so => /home/dave/root/lib/libTree.so (0x00007f7198619000)
	libRint.so => /home/dave/root/lib/libRint.so (0x00007f71983e3000)
	libPostscript.so => /home/dave/root/lib/libPostscript.so (0x00007f7198166000)
	libMatrix.so => /home/dave/root/lib/libMatrix.so (0x00007f7197d29000)
	libPhysics.so => /home/dave/root/lib/libPhysics.so (0x00007f7197a92000)
	libMathCore.so => /home/dave/root/lib/libMathCore.so (0x00007f7197632000)
	libThread.so => /home/dave/root/lib/libThread.so (0x00007f71973e2000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f71971ba000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7196eb8000)
	libfastjettools.so.0 => /home/dave/local/lib/libfastjettools.so.0 (0x00007f7196c75000)
	libfastjet.so.0 => /home/dave/local/lib/libfastjet.so.0 (0x00007f71969e4000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f71966d8000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f71964c2000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f71962a5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7195efb000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f7195ce0000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f7195a72000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f719b92c000)
	libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f7195676000)
	libssl.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f7195416000)
	libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/freetype-infinality/libfreetype.so.6 (0x00007f7195161000)

Hi,

Humm … then it looks like everything is fine … but it isn’t :frowning:

Try with[code]#include “TFile.h”
#include “TTree.h”
#include
#include
#include “TROOT.h”

using namespace std;
int main(void){
gROOT->ProcessLine("#include ");

TFile file(“ntuple.root”);
TTree* tree = dynamic_cast<TTree*>(file.Get(“JPsi”));
std::vector<std::vector > *mu_trk_idx=NULL;
tree->SetBranchAddress(“MUONS_index”,&mu_trk_idx);
cout << tree << " "<< tree->GetName() << " "<< tree->GetEntries()<<endl;
for(int i = 0; i < tree->GetEntries(); i++){
tree->GetEntry(i);
}
return 0;
}[/code]

No dice,

Here’s a dump of what ACLiC is doing under the hood, which superficially appears very different from what I’m doing in my makefile:

CXXFLAGS=-c  -pipe -m64 -W -Woverloaded-virtual -fPIC -pthread
INCDIRS=-I$ROOTSYS/include -I/home/dave/tree-test
echo > "libLoader_C.d"
rmkdepend "-flibLoader_C.d" -o_C.so  -Y -- $(INCDIRS) -- "./libLoader.C"  "-t./libLoader_C.so" > /dev/null 2>&1 
echo ./libLoader_C.so: $ROOTSYS/include/cintdictversion.h $ROOTSYS/include/RVersion.h  >> "libLoader_C.d"
rootcint "--lib-list-prefix=libLoader_C_ACLiC_map" -f "libLoader_C_ACLiC_dict.cxx" -c -p -I$ROOTSYS/include  -I"$ROOTSYS/include"  -D__ACLIC__  "./libLoader.C" "libLoader_C_ACLiC_linkdef.h"
g++ $(CXXFLAGS) -D__ACLIC__ "libLoader_C_ACLiC_dict.cxx" 
g++ "libLoader_C_ACLiC_dict.o" -shared -Wl,-soname,libLoader_C.so -m64 -O2  -Wl,--no-undefined -Wl,--as-needed $ROOTSYS/lib/libCint.so $ROOTSYS/lib/libCore.so $ROOTSYS/lib/libRint.so $ROOTSYS/lib/libMathCore.so $ROOTSYS/lib/libThread.so $ROOTSYS/lib/libRIO.so -o "./libLoader_C.so"
rootcint --lib-list-prefix=libLoader_C_ACLiC_map -f libLoader_C_ACLiC_dict.cxx -c -p -I$ROOTSYS/include -I$ROOTSYS/include -D__ACLIC__ ./libLoader.C libLoader_C_ACLiC_linkdef.h
g++ $(CXXFLAGS) $(INCDIRS)   -D__ACLIC__ libLoader_C_ACLiC_dict.cxx 
g++ libLoader_C_ACLiC_dict.o -shared -Wl,-soname,libLoader_C.so -m64 -O2  -Wl,--no-undefined -Wl,--as-needed $ROOTSYS/lib/libCint.so $ROOTSYS/lib/libCore.so $ROOTSYS/lib/libRint.so $ROOTSYS/lib/libMathCore.so $ROOTSYS/lib/libThread.so $ROOTSYS/lib/libRIO.so -o ./libLoader_C.so 
g++ $(CXXFLAGS)  $(INCDIRS)   -D__ACLIC__ libLoader_C_ACLiC_dict.cxx
g++ libLoader_C_ACLiC_dict.o -m64 -O2  -Wl,--no-undefined -Wl,--as-needed -o libLoader_C_ACLiC_exec $ROOTSYS/lib/libCint.so $ROOTSYS/lib/libCore.so $ROOTSYS/lib/libRint.so $ROOTSYS/lib/libMathCore.so $ROOTSYS/lib/libThread.so $ROOTSYS/lib/libRIO.so -lm -ldl  -pthread   -rdynamic 

Note that this is slightly translated from the raw output since I’m trying to munge it into a makefile rule… The raw output is not so easy to read. I got it by doing:

gDebug=7 .L libLoader.C++
On the root prompt

Hi,

In your failing case, can you send me the content of src/dict.cxx?

Thanks,
Philippe.

OK, after stripping out apparently redundant calls here’s what I’ve come up with:

CXXFLAGS=-c  -pipe -m64 -W -Woverloaded-virtual -fPIC -pthread
INCDIRS=-I$ROOTSYS/include -I/home/dave/tree-test
ROOTLIBS=$ROOTSYS/lib/libCint.so $ROOTSYS/lib/libCore.so $ROOTSYS/lib/libRint.so $ROOTSYS/lib/libMathCore.so $ROOTSYS/lib/libThread.so $ROOTSYS/lib/libRIO.so
echo > "libLoader_C.d"
rmkdepend "-flibLoader_C.d" -o_C.so  -Y -- $(INCDIRS) -- "./libLoader.C"  "-t./libLoader_C.so" > /dev/null 2>&1 
echo ./libLoader_C.so: $ROOTSYS/include/cintdictversion.h $ROOTSYS/include/RVersion.h  >> "libLoader_C.d"
rootcint --lib-list-prefix=libLoader_C_ACLiC_map\
	 -f libLoader_C_ACLiC_dict.cxx\
	 -c -p -I$ROOTSYS/include -I$ROOTSYS/include\
	 -D__ACLIC__ ./libLoader.C libLoader_C_ACLiC_linkdef.h
g++ $(CXXFLAGS) $(INCDIRS)   -D__ACLIC__ libLoader_C_ACLiC_dict.cxx 
g++ libLoader_C_ACLiC_dict.o\
    -shared\
    -Wl,-soname,libLoader_C.so\
    -m64 -O2  -Wl,--no-undefined\
    -Wl,--as-needed $(ROOTLIBS)\
    -o ./libLoader_C.so 
g++ libLoader_C_ACLiC_dict.o\
    -m64 -O2  -Wl,--no-undefined -Wl,--as-needed\
    -o libLoader_C_ACLiC_exec\
    $(ROOTLIBS) -lm -ldl  \
    -pthread   -rdynamic 

This is almost somethign I can conceptualize. Am I correct in inferring that libLoader_C_ACLiC_exec is a special temporary file that is used by the root executable and thus redundant for my purposes? Its compilation is only slightly different than the libLoader_C.so file

Here it is
dict.cxx (10.3 KB)

Hi,

The problem is that the dict.cxx is empty (except for boiler plate code).src/dict.cxx: include/LinkDef.h rootcint -f $@ -c $(CXXFLAGS) -p $^the issue is likely that the LinkDef.h is the only header files. Try also passing an empty header file: rootcint -f $@ -c $(CXXFLAGS) -p empyHeader.h $^

Cheers,
Philippe.

This gets more interesting by the minute. I tried you suggestion. It doesn’t work. For the record here’s the makefile rules:

dummy_header.h:
	$(shell echo > $@)
src/dict.cxx: dummy_header.h include/LinkDef.h
	rootcint -f $@ -c $(CXXFLAGS) -I./include -p $^
src/libDict.so: src/dict.cxx
	$(CC) -shared -fPIC -o$@ $(CXXFLAGS) $^
bin/tree-bug: bin/tree-bug.o src/libDict.so
	$(CC) $^ -o $@ $(LDFLAGS) -L ./src -lDict

Sorry hit submit too soon. Here’s a minimal set of CLI commands that does work:

rmkdepend -f src/libDict.d -o_C.so -Y -- -I$ROOTSYS/include -I./ -I./include -- libLoader.C -t src/libDict.so 
echo ./src/libDict.so: /home/dave/root/include/cintdictversion.h /home/dave/root/include/RVersion.h >> src/libDict.d
rootcint -f src/dict.cxx -c -p -I$ROOTSYS/include -D__ACLIC__ ./libLoader.C libLoader_C_ACLiC_linkdef.h
cat libLoader_C_ACLiC_linkdef.h 
g++ -c  -pipe -m64 -W -Woverloaded-virtual -fPIC -pthread -I$ROOTSYS/include -I./ -D__ACLIC__ src/dict.cxx 
g++ dict.o -shared -Wl,-soname,libDict.so -m64 -O2  -Wl,--no-undefined -Wl,--as-needed $ROOTSYS/lib/libCint.so $ROOTSYS/lib/libCore.so $ROOTSYS/lib/libRint.so $ROOTSYS/lib/libMathCore.so $ROOTSYS/lib/libThread.so $ROOTSYS/lib/libRIO.so -o src/libDict.so 

I don’t think you need any “empyHeader.h”.
You just need to fix your “LinkDef.h”:
#pragma link C++ class std::vector<std::vector >+;

Hi,

Wile is certainly right, I did miss the missing ‘class’ in the #pragma line.

Cheers,
Philippe.

Wow, thanks so much Wile E. Coyote! It works as advertised. Sorry for all the noise. I’ve definitely learned my lesson.