I am trying to add my own ROOT classes.
Here is a simple script I am trying to make work. The file is called test.cpp:
#include "TFile.h"
#include "TTree.h"
#include <iostream>
class A : public TObject {
//class A {
public:
A() {;}
A(int input) : val(input) {;}
int get_val() const { return val; }
~A() {;}
public:
ClassDef(A,1);
private:
int val;
};
class B : public TObject {
//class B {
public:
B() {;}
B(A input_A, int input) : A_in_B(input_A), val(input) {;}
~B() {;}
int get_val() const { return val; }
A A_in_B;
public:
ClassDef(B,1);
private:
int val;
};
int main(){
//void test(){
TTree* t = new TTree("t","description");
A A_object;
B B_object;
TBranch* branch_A = t->Branch("A", &A_object);
TBranch* branch_B = t->Branch("B", &B_object);
for (int i=0; i<10; i++){
A_object = A(i);
B_object = B(A_object, 2*i);
t->Fill();
}
TFile* fOut = new TFile("output.root","RECREATE");
t->Write();
fOut->Close();
return 0;
}
The code runs fine and produces the intended result when compiling with ACLiC.
I tried to compile this with g++ using the my LinkDef.h:
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class A+;
#pragma link C++ class B+;
#endif
and the following commands at the command line:
rootcint test_dictionary.cxx -c test.cpp LinkDef.h
g++ test.cpp $(root-config --libs --cflags) -o test
and get the following errors:
/tmp/ccr2DNfY.o: In function `A::A()':
test.cpp:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0x1f): undefined reference to `vtable for A'
/tmp/ccr2DNfY.o: In function `A::A(int)':
test.cpp:(.text._ZN1AC2Ei[_ZN1AC5Ei]+0x22): undefined reference to `vtable for A'
/tmp/ccr2DNfY.o: In function `A::~A()':
test.cpp:(.text._ZN1AD2Ev[_ZN1AD5Ev]+0x13): undefined reference to `vtable for A'
/tmp/ccr2DNfY.o: In function `B::B()':
test.cpp:(.text._ZN1BC2Ev[_ZN1BC5Ev]+0x20): undefined reference to `vtable for B'
/tmp/ccr2DNfY.o: In function `A::A(A const&)':
test.cpp:(.text._ZN1AC2ERKS_[_ZN1AC5ERKS_]+0x2a): undefined reference to `vtable for A'
/tmp/ccr2DNfY.o: In function `B::B(A, int)':
test.cpp:(.text._ZN1BC2E1Ai[_ZN1BC5E1Ai]+0x27): undefined reference to `vtable for B'
/tmp/ccr2DNfY.o: In function `B::~B()':
test.cpp:(.text._ZN1BD2Ev[_ZN1BD5Ev]+0x14): undefined reference to `vtable for B'
/tmp/ccr2DNfY.o: In function `TBranch* TTree::Branch<A>(char const*, A*, int, int)':
test.cpp:(.text._ZN5TTree6BranchI1AEEP7TBranchPKcPT_ii[_ZN5TTree6BranchI1AEEP7TBranchPKcPT_ii]+0x2f): undefined reference to `typeinfo for A'
test.cpp:(.text._ZN5TTree6BranchI1AEEP7TBranchPKcPT_ii[_ZN5TTree6BranchI1AEEP7TBranchPKcPT_ii]+0x3c): undefined reference to `typeinfo for A'
/tmp/ccr2DNfY.o: In function `TBranch* TTree::Branch<B>(char const*, B*, int, int)':
test.cpp:(.text._ZN5TTree6BranchI1BEEP7TBranchPKcPT_ii[_ZN5TTree6BranchI1BEEP7TBranchPKcPT_ii]+0x2f): undefined reference to `typeinfo for B'
test.cpp:(.text._ZN5TTree6BranchI1BEEP7TBranchPKcPT_ii[_ZN5TTree6BranchI1BEEP7TBranchPKcPT_ii]+0x3c): undefined reference to `typeinfo for B'
collect2: error: ld returned 1 exit status
In general, when adding ROOT classes, must one have separate header and implementation files for each class? If not, what is the problem with my above code?
If one must have separate header and implementation files for each class, I also tried that and received errors. Below is A.hh
#ifndef A_HH
#define A_HH
#include "TObject.h"
class A : public TObject {
public:
A();
A(int input);
~A();
int get_val() const;
public:
ClassDef(A,1);
private:
int val;
};
#endif
Below is A.cc
#include "A.hh"
A::A() {;}
A::A(int input) : val(input) {;}
A::~A() {;}
int A::get_val() const { return val; }
ClassImp(A);
Below is B.hh
#ifndef B_HH
#define B_HH
#include "A.hh"
#include "TObject.h"
class B : public TObject {
public:
B();
B(A input_A, int input);
~B();
int get_val() const;
A A_in_B;
public:
ClassDef(B,1);
private:
int val;
};
#endif
Below is B.cc
#include "A.hh"
#include "B.hh"
B::B() {;}
B::B(A input_A, int input) : A_in_B(input_A), val(input) {;}
B::~B() {;}
int B::get_val() const { return val; }
ClassImp(B);
The LinkDef.h and commands at the command line are the same as before. The error is
/tmp/cchkhdsw.o: In function `__static_initialization_and_destruction_0(int, int)':
A.cc:(.text+0xff): undefined reference to `ROOT::GenerateInitInstance(A const*)'
/tmp/cchkhdsw.o: In function `A::IsA() const':
A.cc:(.text._ZNK1A3IsAEv[_ZNK1A3IsAEv]+0xd): undefined reference to `A::Class()'
/tmp/cchkhdsw.o:(.rodata._ZTV1A[_ZTV1A]+0x1d0): undefined reference to `A::ShowMembers(TMemberInspector&)'
/tmp/cchkhdsw.o:(.rodata._ZTV1A[_ZTV1A]+0x1d8): undefined reference to `A::Streamer(TBuffer&)'
/tmp/cc5KAyy7.o: In function `__static_initialization_and_destruction_0(int, int)':
B.cc:(.text+0x1a1): undefined reference to `ROOT::GenerateInitInstance(B const*)'
/tmp/cc5KAyy7.o: In function `B::IsA() const':
B.cc:(.text._ZNK1B3IsAEv[_ZNK1B3IsAEv]+0xd): undefined reference to `B::Class()'
/tmp/cc5KAyy7.o:(.rodata._ZTV1B[_ZTV1B]+0x1d0): undefined reference to `B::ShowMembers(TMemberInspector&)'
/tmp/cc5KAyy7.o:(.rodata._ZTV1B[_ZTV1B]+0x1d8): undefined reference to `B::Streamer(TBuffer&)'
collect2: error: ld returned 1 exit status
Any help would be appreciated. Thanks.