Hello,
I am trying to create a dictionary and compile a static library libMyTest.a with classes A, B, and C in namespace MyTest. The library is linked against when compiling the executable MyTest from main.cxx. All files are attached in a zip file as well as a compile script containing the required bash commands. The code is also included below in this post.
MyTest::A and MyTest::B are mutually dependent and have to know about each other. MyTest::A has a std:vector as class member. So far, so good, with the help of the ROOT User’s guide and various posts on this forum I have been able to solve a lot of issues.
However, trouble starts again when I try to add to MyTest::A a member function
DoStuffWithBVector( std:vector vectorOfBs) that uses a std:vectorMyTest::B as parameter. Then all of a sudden the good old errors return when linking the library:
MyTestDict.cxx: In function ‘int G__MyTestDict_169_0_2(G__value*, const char*,
G__param*, int)’:
MyTestDict.cxx:554:73: error: ‘B’ was not declared in this scope
((MyTest::A*) G__getstructoffset())->DoStuffWithBVector(*((vector<B>*)
G__int(libp->para[0])));
^
MyTestDict.cxx:554:73: note: suggested alternative:
In file included from MyTestDict.h:34:0,
from MyTestDict.cxx:17:
B.h:10:7: note: ‘MyTest::B’
class B : public TObject
^
MyTestDict.cxx:554:74: error: template argument 1 is invalid
((MyTest::A*) G__getstructoffset())->DoStuffWithBVector(*((vector<B>*)
G__int(libp->para[0])));
^
MyTestDict.cxx:554:74: error: template argument 2 is invalid
MyTestDict.cxx:554:76: error: expected primary-expression before ‘)’ token
((MyTest::A*) G__getstructoffset())->DoStuffWithBVector(*((vector<B>*)
G__int(libp->para[0])));
^
MyTestDict.cxx:554:78: error: expected ‘)’ before ‘G__int’
((MyTest::A*) G__getstructoffset())->DoStuffWithBVector(*((vector<B>*)
G__int(libp->para[0])));
If function DoStuffWithBVector is commented out, everything works again and e.g. the constructor of A can handle a vector just fine.
Does anybodyknow what I am missing or doing wrong here???
MyTestLinkDef.h
#ifdef __CINT__
#pragma link off all class;
#pragma link off all function;
#pragma link off all global;
#pragma link off all typedef;
#pragma link C++ nestedclass;
#pragma link C++ nestedtypedef;
#pragma link C++ namespace MyTest;
#pragma link C++ defined_in namespace MyTest;
#pragma link C++ class MyTest::B+;
#pragma link C++ class std::vector< MyTest::B >+;
#pragma link C++ class MyTest::A+;
#pragma link C++ class MyTest::C+;
#endif
A.h
#ifndef A_H_
#define A_H_
#include <iostream>
#include <vector>
#include <TObject.h>
namespace MyTest
{
class B; // include B.h in implementation file to avoid problems with mutual dependencies
class A : public TObject
{
public:
std::vector<B> fBVec; // List of Bs owned by this A
A(UInt_t numberOfBs = 0);
~A(){}
void DoStuffWithBVector( std::vector<B> vectorOfBs );
ClassDef(A,1); // My class A in my MyTest namespace
};
}; // end of namespace MyTest
#endif // end of A_H_
A.cxx
#include "A.h"
#include "B.h"
ClassImp(MyTest::A)
namespace MyTest
{
A::A(UInt_t numberOfBs) : TObject()
{
for(UInt_t i = 0; i < numberOfBs; i++)
{
B b(this,fBVec.size()-1);
fBVec.push_back(b);
}
}
void A::DoStuffWithBVector( std::vector<B> vectorOfBs )
{
for(UInt_t i = 0; i < vectorOfBs.size(); i++) std::cout << i << "\t" << vectorOfBs[i].fA << std::endl;
}
}; // end of namespace MyTest
B.h
#ifndef B_H_
#define B_H_
#include "TObject.h"
namespace MyTest
{
class A; // include A.h in implementation file to avoid problems with mutual dependencies
class B : public TObject
{
public:
A *fA;
Int_t fID;
B(A *a = 0, Int_t id = -1);
~B() {}
ClassDef(B,1); // My class B in my MyTest namespace
};
}; // end of namespace MyTest
#endif // end of B_H_
B.cxx
#include "B.h"
#include "A.h"
ClassImp(MyTest::B)
namespace MyTest
{
B::B(A *a, Int_t id) : TObject()
{
fA = a;
fID = id;
}
}; // end of namespace MyTest
MyTest.h
#ifndef MYTEST_H_
#define MYTEST_H_
#include <vector>
#include "B.h"
#include "A.h"
namespace MyTest
{
class C : public TObject
{
protected:
A *fA;
public:
C(UInt_t numberOfBsInA = 0);
~C();
A *GetA();
ClassDef(C,1); // My class C in my MyTest namespace
};
}; // end of namespace MyTest
#endif // end of MYTEST_H_
MyTest.cxx
#include "MyTest.h"
ClassImp(MyTest::C);
namespace MyTest
{
C::C(UInt_t numberOfBsInA)
{
fA = new A(numberOfBsInA);
}
C::~C()
{
delete fA;
}
A *C::GetA()
{
return fA;
}
}; // end of namespace MyTest
main.cxx
#include <iostream>
#include <../TestProject/MyTest.h>
int main(int argc, char **argv) {
MyTest::C *c = new MyTest::C(10);
std::cout << "MyTest::C *c = " << c << "\t\tc->fBVec.size() = " << c->GetA()->fBVec.size() << std::endl;
return 0;
}
compile.sh
#!/bin/bash
ProjectName=MyTest
# clean up
rm -f ${ProjectName} *Dict* *o *a *~
# generate dictionary
#rootcint -f ${ProjectName}Dict.cxx -c -p ${ProjectName}.h ${ProjectName}LinkDef.h
rootcint -f ${ProjectName}Dict.cxx -c -p B.h A.h ${ProjectName}.h ${ProjectName}LinkDef.h
# compile library
`root-config --cxx --cflags` -W -Wall -fPIC -c B.cxx A.cxx ${ProjectName}.cxx
#`root-config --cxx --cflags` -W -Wall -fPIC -c B.cxx A.cxx ${ProjectName}Dict.cxx ${ProjectName}.cxx
# static library
ar rvs lib${ProjectName}.a *.o
# shared library
#`root-config --cxx --cflags` -W -Wall -fPIC -shared -o lib${ProjectName}.so *.o `root-config --glibs`
# compile executable using library and dictionary
`root-config --cxx --cflags` -W -Wall -fPIC -o ${ProjectName} main.cxx ${ProjectName}Dict.cxx `root-config --cflags --glibs` -L. -l${ProjectName}
# compile executable using library without dictionary
#`root-config --cxx --cflags` -W -Wall -fPIC -o ${ProjectName} main.cxx `root-config --cflags --glibs` -L. -l${ProjectName}
MyTest.zip (3.17 KB)