c++ - 从 DLL 导出 STL std::basic_string 模板时,出现 LNK2005 错误

标签 c++ visual-studio-2010 dll stl

好的,所以我已经阅读了几个关于这个主题的问题和文章,我觉得我了解基础知识,但我仍然遇到问题。

我有一个 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 是一个私有(private)变量,它只能由成员函数访问,它可能安全地忽略警告...对此有何评论?这是朝着正确方向迈出的一步吗?

动态链接库代码:

#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; }

执行代码:

#include <iostream>
#include "SampleDLL.h"

using namespace std;

void main()
{
    MyClass class1;

    cout << class1.getData() << endl;

}

最佳答案

您似乎看到了 connect.microsoft.com 中描述的问题.

那里建议了一个解决方法,但它似乎有点讨厌。

其他可能有帮助的选项:

  1. 不要导出 std::string,而是在 DLL 接口(interface)中使用 const char *(参见 https://stackoverflow.com/a/5340065/12663)
  2. 确保 _ITERATOR_DEBUG_LEVEL 匹配您的所有项目

关于c++ - 从 DLL 导出 STL std::basic_string 模板时,出现 LNK2005 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8976617/

相关文章:

c++ - 指向数组访问的指针出现段错误

c++ - 编译器是否提供地址运算符?

security - 保护 dll 文件的最佳方法是什么

java - jna加载库

java - 将 maven 与来自第三方的 DLL 结合使用并管理 DLL 的名称

c++ - 内存 DC 上的 SelectObject

c++ - WinSock closesocket() 调用在某些计算机上需要一秒钟

visual-studio-2010 - visual studio 2010 CTP 到期解决方法

.net - 运行 Visual Studio 2010 实例并以编程方式附加到进程?

visual-studio-2010 - 我可以在VS2010中关闭上下文菜单滚动吗?