DLL에서 익스포트할 클래스에서 STL 클래스 멤버를 쓰는 것은 바람직하지 않지만, 세상사란 그리 만만하지 않은 법. DLL에서 STL클래스를 익스포트 해야 할 경우가 가끔 생기는데, 사실 vector같은 건 별로 문제가 되지 않는다. 컨테이너 자체가 간단하고, 연관된 할당자도 별로 없기 때문에. 사실 map이나 set같은 복잡한 컨테이너가 진짜 문제다.
웹에서 찾아볼 수 있는, STL map을 DLL에서 익스포트하기 위한 매크로는 대개 다음과 같다
#define EXPORT_STL_MAP( dllmacro, mapkey, mapvalue ) \
template struct
dllmacro std::pair< mapkey,mapvalue >; \
template class dllmacro
std::allocator< \
std::pair<const mapkey,mapvalue> >; \
template struct dllmacro std::less< mapkey >; \
template class
dllmacro std::allocator< \
std::_Tree_ptr<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>,
\
std::allocator<std::pair<const mapkey,mapvalue> >,false>
> >; \
template class dllmacro std::allocator< \
std::_Tree_nod<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>,
\
std::allocator<std::pair<const mapkey,mapvalue> >,false>
> >; \
template class dllmacro std::_Tree_nod< \
std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
std::allocator<std::pair<const mapkey,mapvalue> >,false> >;
\
template class dllmacro std::_Tree_ptr< \
std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
std::allocator<std::pair<const mapkey,mapvalue> >,false> >;
\
template class dllmacro std::_Tree_val< \
std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
std::allocator<std::pair<const mapkey,mapvalue> >,false> >;
\
template class dllmacro std::map< \
mapkey, mapvalue,
std::less< mapkey >, \
std::allocator<std::pair<const
mapkey,mapvalue> > >;
(이걸보고 주눅이 안들면 비정상. 안심해라)
근데 이 매크로를 써서 map을 익스포트하면, VC2003에서는 아무 탈 없이 컴파일 됐는데, VC2005에서는 요상하게 다음과 같은 에러를 뱉었다.
1>c:\dev\visualstudio8\vc\include\xtree(61) : warning C4251: 'std::_Tree_nod<_Traits>::_Alnod' : class 'std::allocator<_Ty>'에서는
class 'std::_Tree_nod<_Traits>'의 클라이언트에서 DLL 인터페이스를 사용하도록 지정해야 합니다.
1> with
1> [
1>
_Traits=std::_Tmap_traits<int,short,std::less<int>,std::allocator<std::pair<const int,short>>,false>
1> ]
1>
and
1> [
1>
_Ty=std::_Tree_nod<std::_Tmap_traits<int,short,std::less<int>,std::allocator<std::pair<const int,short>>,false>>::_Node
1>
]
1> and
1> [
1>
_Traits=std::_Tmap_traits<int,short,std::less<int>,std::allocator<std::pair<const int,short>>,false>
1> ]
(보통 STL이 뱉는 에러메시지는 암호같긴 하다)
이걸 해석하는 것도 만만치 않긴 하지만, 해석하자면 std::allocator< ... >::_Node 가 익스포트되도록 지정되지 않았다..는 내용. 따라서 다음 두 줄을 매크로 선언에 추가하면 된다. 위의 메시지는 _Node에 대한 것이고, _Node에 대한 할당자를 익스포트하도록 지정하면 또 다른 어딘가에서 _Node*에 대한 할당자도 익스포트해야 한다는 메시지가나온다. 그래서 두줄을 더 추가해야 했다.
template class dllmacro std::allocator< \
std::_Tree_nod<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>,
\
std::allocator<std::pair<const mapkey,mapvalue> >,false>
>::_Node >; \
template class dllmacro std::allocator< \
std::_Tree_nod<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>,
\
std::allocator<std::pair<const mapkey,mapvalue> >,false>
>::_Node* >; \
2003에서는 멀쩡히 잘 돌아가던 매크로가 2005에서는 안되는 이유가 뭔지는 잘 모르겠지만 -_- 여튼 저렇게 하니까 됐다. 잊어먹지 말자.