【发布时间】:2012-01-23 18:23:46
【问题描述】:
好的,所以我已经阅读了一些关于这个主题的问题和文章,我觉得我了解了基础知识,但我仍然遇到了麻烦。
我有一个 DLL,它导出了一个包含 std::string 作为成员的类。 我的主程序包含也有字符串的类,它使用 DLL。
如果我在 VS2010 中编译 DLL,我会收到以下警告:
warning C4251: 'MyClass::data' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'MyClass'
当我编译 EXE 时,我得到相同的警告,但没有错误,程序编译并运行。实际上,这是一个大型项目,所以我收到了 40 条警告,我对此并不太感兴趣。 (作为一个侧面观察,使用 VS2008 编译时不会出现这些警告)
所以,我读到了那个警告,它把我带到了这篇 MS 文章: http://support.microsoft.com/default.aspx?scid=KB;EN-US;168958 它告诉如何从 DLL 中导出 STL 模板以满足我收到的警告。
问题是,当我添加以下行以删除警告时:
EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator<char>;
EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits<char>, std::allocator<char> >;
DLL 编译时没有任何警告,但是当我编译我的 EXE 时,链接器会出错:
2>SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in OtherClass.obj
2>SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: unsigned int __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::size(void)const " (?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ) already defined in OtherClass.obj
DLL 和 EXE 都使用相同的代码生成选项进行编译。我可以在两者上使用 MT,也可以在 MD 上使用,结果是一样的。
我将包含来自最小化示例程序的代码,以防我在上面遗漏任何内容。
我的主要问题是:我可以修复 LNK2005 错误,还是忽略 C4251 警告是否安全?
编辑:所以我读了更多,看起来如果 DLL 类使用的 std::string 是一个只能由成员函数访问的私有变量,它可能可以安全地忽略警告......关于这个的任何cmets?这是朝着正确方向迈出的一步吗?
DLL 代码:
#pragma once
#include <exception>
#include <string>
#ifdef SAMPLEDLL_EXPORTS
# define DECLSPECIFIER __declspec(dllexport)
# define EXPIMP_TEMPLATE
#else
# define DECLSPECIFIER __declspec(dllimport)
# define EXPIMP_TEMPLATE extern
#endif
//disable warnings on extern before template instantiation (per MS KB article)
#pragma warning (disable : 4231)
//std::basic_string depends on this allocator, so it must also be exported.
EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator<char>;
//std::string is a typedef, so you cannot export it. You must export std::basic_string
EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits<char>, std::allocator<char> >;
#pragma warning (default : 4231)
class DECLSPECIFIER MyClass
{
public:
std::string getData(); //returns 'data', body in CPP file
private:
std::string data;
int data2;
};
//in SampleDLL.cpp file...
std::string MyClass::getData() { return data; }
EXE 代码:
#include <iostream>
#include "SampleDLL.h"
using namespace std;
void main()
{
MyClass class1;
cout << class1.getData() << endl;
}
【问题讨论】:
-
马克:我确实读过那个问题,但它似乎没有为我所看到的问题提供答案,因为它没有提到我现在遇到的额外 LNK2005 问题。
标签: c++ visual-studio-2010 dll stl