Template et probleme au linkage (seulement windows)
Bonjour,
J'ai un probleme avec l'utilisation de templates quand je suis au moment du linkage.
------------------------------------
Dans une librairie A je creer une templates:
include/libA/paramsnodevec.h
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
template <typename _Tp>
class X7S_CX_DLL ParamsNodeVec: public ParamsNode
{
public:
ParamsNodeVec(ParamsNode *parent, const std::string& name, int ID=X7S_ANY_ID)
:ParamsNode(parent,name, X7S_ANY_TYPE, ID) {};
virtual ~ParamsNodeVec() { deleteAll(); };
bool append(_Tp* obj)
{
bool isok=true;
if(obj)
{
//Check that it has the same parent
if(((ParamsNode*)obj)->getParent() != this)
{
//Otherwise add it to the XmlList
isok=this->addAsChild(obj);
}
else
{
//Otherwise check for duplicate (in the list)
for(int i=0;i<length();i++)
{
if(obj==m_vec[i]) isok=false;
}
}
if(isok) m_vec.push_back(obj);
}
return isok;
}
const _Tp* at(int index) const
{
if(0 <= index && index < length())
return m_vec.at(index);
else
{
return NULL;
}
}
_Tp* at(int index)
{
if(0 <= index && index < length())
return m_vec.at(index);
else
{
return NULL;
}
}
const std::vector<_Tp*> vec() { return m_vec; }
_Tp* remove(int index)
{
_Tp* ret=NULL;
if(0<= index && index < length())
{
ret=m_vec[index];
m_vec.erase(m_vec.begin()+index);
}
return ret;
}
bool erase(int index)
{
_Tp* tmp = this->remove(index);
if(tmp)
{
delete tmp;
return true;
}
return false;
}
size_t size() const { return m_vec.size(); }
int length() const { return (int)m_vec.size(); }
/**
* @brief Generic method to create a child giving all the information
*
* This method is one called by the XML library
*/
bool createChild(const std::string& name, int type, int id, int pos)
{
bool ret=false;
if(name.compare(_Tp::nodeName())==0)
{
//Delete all other child if we are the first one.
if(pos==ParamsNode::First) this->deleteAll();
//Call the new function to create children
_Tp *tmp = this->newChild(type);
if(tmp)
{
ret = this->append(tmp);
if(ret && id != X7S_ANY_ID)
{
ret = this->setChildID(tmp,id);
if(ret==false)
{
_X7S_DEBUG_CL_M("createChild()",ECAT_CORE,ELVL_INF,Err_Duplicate,"Can not append %s to %s because ID %d already exist",
tmp->name().c_str(),this->name().c_str(),id);
this->erase(size()-1);
}
}
}
}
return ret;
}
protected:
void deleteAll()
{
//Copy all the value in a temporary vector
std::vector<_Tp*> tmpVec=m_vec;
//Clear the vector (not usable in other thread)
m_vec.clear();
//Delete the value one by one from the temporary vector.
for(size_t i=0;i<tmpVec.size();i++)
{
X7S_DELETE_PTR(tmpVec[i]);
}
}
/**
* @brief Virtual method to create a child
*
* This method must be overloaded in the class that will implement it.
* The child created can be with a NULL parent, because we will add it.
*
* @param type
*/
virtual _Tp* newChild(int type)=0;
protected:
std::vector<_Tp* > m_vec;
}; |
Dans une librarie B (qui depend de A) je creer les fichiers suivants:
libB/shapes.h
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include <core/paramsnodevec.h>
class Shape; //!< Prototype
class X7S_CVPP_DLL Shapes: public ParamsNodeVec<Shape>
{
public:
Shapes(ParamsNode *parent, const cv::Size& reso);
virtual ~Shapes();
void draw(cv::Mat& im) const;
const cv::Size& resolution() const { return m_reso; }
protected:
Shape* newChild(int type);
void initParams() {};
protected:
cv::Size m_reso;
}; |
libB/shapes.cpp
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
Shapes::Shapes(ParamsNode *parent, const cv::Size& reso)
:ParamsNodeVec<Shape>(parent,"shapes"), m_reso(reso)
{
}
Shapes::~Shapes()
{
}
void Shapes::draw(cv::Mat& img) const
{
Shape *shape;
for(size_t i=0;i<m_vec.size();i++)
{
shape=m_vec[i];
if(shape) shape->draw(img);
}
}
Shape* Shapes::newChild(int type)
{
Shape *s= Shape::create(type);
if(s) s->setResolution(m_reso);
return s;
} |
------------------------------------
Avec MinGW j'ai les erreurs suivantes:
Code:
1 2 3 4 5 6 7 8 9
|
Linking CXX shared library ..\..\..\bin\libx7scvpp.dll
cd C:\Users\Ben\project\builds\CvS400\ecVGA\x7s\modules\cvpp && "C:\Program Files\CMake 2.8\bin\cmake.exe" -E cmake_link_script CMakeFiles\x7scvpp.dir\link.txt --verbose=1
C:\MinGW\bin\g++.exe -shared -o ..\..\..\bin\libx7scvpp.dll -Wl,--out-implib,..\..\..\lib\libx7scvpp.dll.a -Wl,--major-image-version,1,--minor-image-version,1 -Wl,@CMakeFiles\x7scvpp.dir\objects1.rsp ..\..\..\lib\libx7score.dll.a ..\..\..\lib\libx7scv.dll.a C:\Libs\OpenCV\installed\lib\libcxcore210d.dll.a C:\Libs\OpenCV\installed\lib\libcv210d.dll.a C:\Libs\OpenCV\installed\lib\libml210d.dll.a C:\Libs\OpenCV\installed\lib\libhighgui210d.dll.a C:\Libs\OpenCV\installed\lib\libcvaux210d.dll.a ..\..\..\3rdparty\lib\liblibjpeg.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
CMakeFiles/x7scvpp.dir/src/shape.cpp.obj:shape.cpp:(.text$_ZN3x7s13ParamsNodeVecINS_5ShapeEEC2EPNS_10ParamsNodeERKSsi[x7s::ParamsNodeVec<x7s::Shape>::ParamsNodeVec(x7s::ParamsNode*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)]+0x67): undefined reference to `_imp___ZTVN3x7s13ParamsNodeVecINS_5ShapeEEE'
CMakeFiles/x7scvpp.dir/src/shape.cpp.obj:shape.cpp:(.text$_ZN3x7s13ParamsNodeVecINS_5ShapeEEC1EPNS_10ParamsNodeERKSsi[x7s::ParamsNodeVec<x7s::Shape>::ParamsNodeVec(x7s::ParamsNode*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)]+0x67): undefined reference to `_imp___ZTVN3x7s13ParamsNodeVecINS_5ShapeEEE'
CMakeFiles/x7scvpp.dir/src/shape.cpp.obj:shape.cpp:(.text$_ZN3x7s13ParamsNodeVecINS_5ShapeEED2Ev[x7s::ParamsNodeVec<x7s::Shape>::~ParamsNodeVec()]+0x36): undefined reference to `_imp___ZTVN3x7s13ParamsNodeVecINS_5ShapeEEE'
CMakeFiles/x7scvpp.dir/src/shape.cpp.obj:shape.cpp:(.text$_ZN3x7s13ParamsNodeVecINS_5ShapeEED1Ev[x7s::ParamsNodeVec<x7s::Shape>::~ParamsNodeVec()]+0x36): undefined reference to `_imp___ZTVN3x7s13ParamsNodeVecINS_5ShapeEEE'
CMakeFiles/x7scvpp.dir/src/shape.cpp.obj:shape.cpp:(.text$_ZN3x7s13ParamsNodeVecINS_5ShapeEED0Ev[x7s::ParamsNodeVec<x7s::Shape>::~ParamsNodeVec()]+0x36): undefined reference to `_imp___ZTVN3x7s13ParamsNodeVecINS_5ShapeEEE' |
Avec MVC2008 j'obtient comme message:
Code:
1 2 3 4 5 6 7 8 9 10
|
1> Creating library C:\Users\Ben\project\builds\CvS400\vc9VGA-2\lib\Debug\x7scvpp.lib and object C:\Users\Ben\project\builds\CvS400\vc9VGA-2\lib\Debug\x7scvpp.exp
1>shape.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall x7s::ParamsNodeVec<class x7s::Shape>::~ParamsNodeVec<class x7s::Shape>(void)" (__imp_??1?$ParamsNodeVec@VShape@x7s@@@x7s@@UAE@XZ) referenced in function "public: virtual __thiscall x7s::Shapes::~Shapes(void)" (??1Shapes@x7s@@UAE@XZ)
1>shape.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall x7s::ParamsNodeVec<class x7s::Shape>::ParamsNodeVec<class x7s::Shape>(class x7s::ParamsNodeVec<class x7s::Shape> const &)" (__imp_??0?$ParamsNodeVec@VShape@x7s@@@x7s@@QAE@ABV01@@Z) referenced in function "public: __thiscall x7s::Shapes::Shapes(class x7s::Shapes const &)" (??0Shapes@x7s@@QAE@ABV01@@Z)
1>shape.obj : error LNK2001: unresolved external symbol "public: virtual bool __thiscall x7s::ParamsNodeVec<class x7s::Shape>::createChild(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int,int,int)" (?createChild@?$ParamsNodeVec@VShape@x7s@@@x7s@@UAE_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HHH@Z)
1>shape.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class x7s::ParamsNodeVec<class x7s::Shape> & __thiscall x7s::ParamsNodeVec<class x7s::Shape>::operator=(class x7s::ParamsNodeVec<class x7s::Shape> const &)" (__imp_??4?$ParamsNodeVec@VShape@x7s@@@x7s@@QAEAAV01@ABV01@@Z) referenced in function "public: class x7s::Shapes & __thiscall x7s::Shapes::operator=(class x7s::Shapes const &)" (??4Shapes@x7s@@QAEAAV01@ABV01@@Z)
1>shape.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall x7s::ParamsNodeVec<class x7s::Shape>::ParamsNodeVec<class x7s::Shape>(class x7s::ParamsNode *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int)" (__imp_??0?$ParamsNodeVec@VShape@x7s@@@x7s@@QAE@PAVParamsNode@1@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) referenced in function "public: __thiscall x7s::Shapes::Shapes(class x7s::ParamsNode *,class cv::Size_<int> const &)" (??0Shapes@x7s@@QAE@PAVParamsNode@1@ABV?$Size_@H@cv@@@Z)
1>shape.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: bool __thiscall x7s::ParamsNodeVec<class x7s::Shape>::append(class x7s::Shape *)" (__imp_?append@?$ParamsNodeVec@VShape@x7s@@@x7s@@QAE_NPAVShape@2@@Z) referenced in function "public: __thiscall x7s::Shape::Shape(int,class x7s::Shapes *)" (??0Shape@x7s@@QAE@HPAVShapes@1@@Z)
1>C:\Users\Ben\project\builds\CvS400\vc9VGA-2\bin\Debug\x7scvpp.dll : fatal error LNK1120: 6 unresolved externals
1>Build log was saved at "file://c:\Users\Ben\project\builds\CvS400\vc9VGA-2\x7s\modules\cvpp\x7scvpp.dir\Debug\BuildLog.htm" |
Sous linux tout compil correctement.
--------------------------------------
J'ai regarder dans plusieurs FAQ et je ne comprend pas ou est l'erreur car j'ai la declaration complete dans mon fichier .h