Hello,
This is a follow up to one of my earlier questions “Add Own ROOT Classes” (Add Own ROOT Classes).
My problem is that I would like to access my custom ROOT class from a directory that does not contain any of the shared library files (or any other files that ROOT creates, etc.). That was probably not a very good description, so I have made a minimal example of my problem. I am using /mnt/misc/sw/x86_64/Debian/8/root/gnu/6.04.02/bin/root.
Here are the following files I use.
This file is called A.h:
class A {
public:
A() : val(0) {;}
A(int input) : val(input) {;}
int get_val() const { return val; }
public:
ClassDef(A,1);
private:
int val;
};
This file is called A.cpp:
#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include "A.h"
int main(){
A A_object;
TTree* t = new TTree("t","description");
t->Branch("A", &A_object);
for (int i=0; i<10; i++){
A_object = A(i);
t->Fill();
}
TFile* fOut = new TFile("output.root","RECREATE");
t->Write();
fOut->Close();
return 0;
}
This file is LinkDef.h:
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class A+;
And here is the build script I use:
rm A_dictionary.cxx
rootcling A_dictionary.cxx -rml libA.so -rmf libA.rootmap A.h LinkDef.h
g++ A_dictionary.cxx `root-config --libs --cflags` -o libA.so -fPIC -shared
g++ A.cpp $(root-config --cflags) $(root-config --glibs) libA.so -std=c++11 -O3 -o my_executable
I then run my_executable. This produces the intended result: a root file with a tree that was filled as I expected. Now I would like to analyze the contents of this tree. I do so with this script named analyze_tree.C (which I compile with ACLiC, using .L analyze_tree.C++g):
#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include "A.h"
void analyze_tree(){
TFile* fIn = new TFile("output.root","READ");
TTree* tIn = (TTree*) fIn->Get("t");
A* A_pointer = new A;
tIn->SetBranchAddress("A", &A_pointer);
int num = tIn->GetEntries();
for (int i=0; i<num; i++){
tIn->GetEntry(i);
std::cout << A_pointer->get_val() << std::endl;
}
}
Running this script in the same directory as all the other files produces the intended result. Now here comes my problem. I want to move analyze_tree.C to a different directory and run it from this new directory. My first step was to just change the pathways to the header file and the ROOT file, as shown here:
#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include "../A.h" // ** modify path **
void analyze_tree(){
TFile* fIn = new TFile("../output.root","READ"); // ** modify path **
TTree* tIn = (TTree*) fIn->Get("t");
A* A_pointer = new A;
tIn->SetBranchAddress("A", &A_pointer);
int num = tIn->GetEntries();
for (int i=0; i<num; i++){
tIn->GetEntry(i);
std::cout << A_pointer->get_val() << std::endl;
}
}
This returns the following error:
root [0] .L analyze_tree.C++g
Info in <TUnixSystem::ACLiC>: creating shared library /user/my_name/root_forums/new_directory/./analyze_tree_C.so
/user/my_name/root_forums/new_directory/analyze_tree_C_ACLiC_dict.o: In function `A::A()':
/user/my_name/root_forums/new_directory/./../A.h:5: undefined reference to `vtable for A'
/user/my_name/root_forums/new_directory/analyze_tree_C_ACLiC_dict.o: In function `int TTree::SetBranchAddress<A>(char const*, A**, TBranch**)':
/mnt/misc/sw/x86_64/Debian/8/root/gnu/6.04.02/include/root/TTree.h:505: undefined reference to `typeinfo for A'
/mnt/misc/sw/x86_64/Debian/8/root/gnu/6.04.02/include/root/TTree.h:507: undefined reference to `typeinfo for A'
collect2: error: ld returned 1 exit status
Error in <ACLiC>: Compilation failed!
I searched around and found some information about gSystem->Load. I tried this, and it works as intended:
root [0] gSystem->Load("../libA.so");
root [1] .L analyze_tree.C++g
Info in <TUnixSystem::ACLiC>: creating shared library /user/my_name/root_forums/new_directory/./analyze_tree_C.so
root [2] analyze_tree()
0
1
2
3
4
5
6
7
8
9
So then I thought I could put this gSystem load command into analyze_tree.C as shown here:
#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include "TSystem.h" // ** I think this is the header for gSystem? **
#include "../A.h" // ** modify path **
void analyze_tree(){
gSystem->Load("../libA.so"); // ** same command used previously **
TFile* fIn = new TFile("../output.root","READ"); // ** modify path **
TTree* tIn = (TTree*) fIn->Get("t");
A* A_pointer = new A;
tIn->SetBranchAddress("A", &A_pointer);
int num = tIn->GetEntries();
for (int i=0; i<num; i++){
tIn->GetEntry(i);
std::cout << A_pointer->get_val() << std::endl;
}
}
But now the error is as it was before:
root [0] .L analyze_tree.C++g
Info in <TUnixSystem::ACLiC>: creating shared library /user/my_name/root_forums/new_directory/./analyze_tree_C.so
/user/my_name/root_forums/new_directory/analyze_tree_C_ACLiC_dict.o: In function `A::A()':
/user/my_name/root_forums/new_directory/./../A.h:5: undefined reference to `vtable for A'
/user/my_name/root_forums/new_directory/analyze_tree_C_ACLiC_dict.o: In function `int TTree::SetBranchAddress<A>(char const*, A**, TBranch**)':
/mnt/misc/sw/x86_64/Debian/8/root/gnu/6.04.02/include/root/TTree.h:505: undefined reference to `typeinfo for A'
/mnt/misc/sw/x86_64/Debian/8/root/gnu/6.04.02/include/root/TTree.h:507: undefined reference to `typeinfo for A'
collect2: error: ld returned 1 exit status
Error in <ACLiC>: Compilation failed!
Any help would be appreciated. I showed above one method that works: typing gSystem->Load("…/libA.so") before compiling with ACLiC. However, I would like to not have to do this, but rather somehow incorporate it into my analyze_tree.C script.