Exporting classes containing std:: objects (vector, map, etc) from a dll

From: http://www.abstraction.net/ViewArticle.aspx?articleID=83


Related readings:

http://stackoverflow.com/questions/767579/exporting-classes-containing-std-objects-vector-map-etc-from-a-dll

http://www.cplusplus.com/forum/general/78467/


STL and DLLs

 

By George Mihaescu

 

This article is now obsolete: the described behavior applies only up to (and including) Visual Studio 5.0. After that version the STL and compiler implementations have changed so that the behavior described here is not an issue anymore.

 

Summary: this article describes potential problems when exporting from a DLL classes that are based on (or contain public members based on) STL types and provides a solution.

The problem

The use of various classes from STL in DLLs raises a major problem: STL template instantiations cannot be exported directly from the DLL, the main reason being the fact that a few of the STL templates make use of static members. By exposing in a header an STL template instantiation, the DLL and the user of the DLL (that includes the exposed header) get different copies of the static members, and this leads to unpredictable behavior and random crashes.

This problem is documented in the MSDN and various means to resolve it are described.

The solution

The most elegant manner of solving the problem is to provide wrapper classes for the STL template instantiations, and those wrappers are exported from the DLL, as shown below.

For instance, instead of exposing a header from a DLL like this:

 

#include <map>             //for STL map

 

using namespace std;

 

class __declspec(dllexport) MyClass

{

};

 

typedef __declspec (dllexport)  map <int, MyClass>   AMap;

 

 

use a header like this:

 

 

#include <map>             //for STL map

 

using namespace std;

 

class __declspec(dllexport) MyClass

{

};

 

//wrapper class for the map

class __declspec(dllexport) AMap

{

       public:

              AMap ();

              ~AMap ();

 

//wrapper methods for the aggregated map:

              void Insert (const MyClass& m);

              const MyClass* Find (int key);

 

       private:

              typedef map <int, MyClass>   _AMap;

 

       AMap   m_map; //the wrapped map

};

 

 

When implementing the header exposed by the DLL this way, the compiler will generate a warning similar to “class std::map <int, MyClass> must have DLL interface to be used by clients of MyDll.dll”. This is usually with no consequences (it means that friends of the class AMap -if any- will not be able to directly access the wrapped map because it is not exported from the DLL). However, the direct usage of the map by clients of the DLL was not possible anyway due to the problem we were trying to solve in the first place - so this warning is of no concern.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值