dev.log2008. 2. 1. 04:51

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에서는 안되는 이유가 뭔지는 잘 모르겠지만 -_- 여튼 저렇게 하니까 됐다. 잊어먹지 말자.


Posted by uhm