您的位置:首页 > 移动开发 > Objective-C

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

2012-11-05 13:52 501 查看
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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: