从 dll 导出 std::vector 时出现链接错误
Linking errors while exporting std::vector from dll
我有一个使用 __declspec(dllexport)
导出结构的 dll (my_library.dll
)。由于此结构包含一个 std::vector<std::wstring> member
,我还为其导出函数,如下所示:
template class __declspec(dllexport) std::allocator<std::wstring>;
template class __declspec(dllexport) std::vector<std::wstring>;
请注意,我已经定义了宏,这样 dll 在编译时导出 struct 和 vector 之上,并且它们被导入(当 dll 被另一个应用程序使用时通过 __declspec(dllimport))
。
上面的 dll 构建良好。
现在这个 my_library.dll(和相应的 my_library.lib
)链接到一个 exe(my_exe.exe
)。此 exe 有一个定义 global std::vector<std::wstring>
变量的 .cpp 文件 (exe_source.cpp
)。这个源文件编译得很好。
但是,在构建此 exe 时,出现以下错误:
my_library.lib(my_library.dll) : error LNK2005: "public: __thiscall
std::vector,class std::allocator
,class std::allocator,class std::allocator
::~vector,class std::allocator
,class std::allocator,class std::allocator
(void)" (??1?$vector@V?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@V?$allocator@V?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@@std@@QAE@XZ) already defined in exe_source.obj
我怀疑 my_library.dll 定义并导出了所有 std::vector<std::wstring>
函数,并且在 exe_source.cpp
中使用全局 std::vector<std::wstring>
变量也会导致定义许多 std::vector<std::wstring>
函数,导致链接器抱怨发现此类函数的多个定义。
我理解错误了吗?
如何解决这个问题?
感谢您的宝贵时间。
首先,在 DLL 接口处使用 STL 类 是一个 高度受限的 设计选择:事实上,DLL 和使用它的其他模块(例如 EXE由您的 DLL 客户端构建)必须使用 相同 C++ 编译器版本构建并链接到 CRT DLL 的 相同 风格。
更好的设计选择是使用 纯 C 接口导出 DLL(实现 可以使用 C++,但您应该将public API 使其成为 C),或使用 COM-like 导出 C++ 抽象接口 的方法,如建议 this CodeProject article.
假设您知道这一点,您应该能够删除以下行:
template class __declspec(dllexport) std::allocator<std::wstring>;
template class __declspec(dllexport) std::vector<std::wstring>;
并且只导出承载您的 STL 数据成员的结构,例如:
MyLib.h
#pragma once
#ifndef MYLIB_API
#define MYLIB_API __declspec(dllimport)
#endif
#include <string>
#include <vector>
struct MYLIB_API MyLib_Data
{
std::vector<std::wstring> Strings;
// ... other stuff ...
};
MyLib.cpp
#define MYLIB_API __declspec(dllexport)
#include "MyLib.h"
// ... Implementation code ...
请注意,您可能会收到一条警告 C4251,类似于:
'MyLib_Data::Strings' : class 'std::vector<std::wstring,std::allocator<_Ty>>'
needs to have dll-interface to be used by clients of struct 'MyLib_Data'
但你可以忽略它。
我有一个使用 __declspec(dllexport)
导出结构的 dll (my_library.dll
)。由于此结构包含一个 std::vector<std::wstring> member
,我还为其导出函数,如下所示:
template class __declspec(dllexport) std::allocator<std::wstring>;
template class __declspec(dllexport) std::vector<std::wstring>;
请注意,我已经定义了宏,这样 dll 在编译时导出 struct 和 vector 之上,并且它们被导入(当 dll 被另一个应用程序使用时通过 __declspec(dllimport))
。
上面的 dll 构建良好。
现在这个 my_library.dll(和相应的 my_library.lib
)链接到一个 exe(my_exe.exe
)。此 exe 有一个定义 global std::vector<std::wstring>
变量的 .cpp 文件 (exe_source.cpp
)。这个源文件编译得很好。
但是,在构建此 exe 时,出现以下错误:
my_library.lib(my_library.dll) : error LNK2005: "public: __thiscall std::vector,class std::allocator
,class std::allocator,class std::allocator
::~vector,class std::allocator ,class std::allocator,class std::allocator (void)" (??1?$vector@V?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@V?$allocator@V?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@2@@std@@QAE@XZ) already defined in exe_source.obj
我怀疑 my_library.dll 定义并导出了所有 std::vector<std::wstring>
函数,并且在 exe_source.cpp
中使用全局 std::vector<std::wstring>
变量也会导致定义许多 std::vector<std::wstring>
函数,导致链接器抱怨发现此类函数的多个定义。
我理解错误了吗?
如何解决这个问题?
感谢您的宝贵时间。
首先,在 DLL 接口处使用 STL 类 是一个 高度受限的 设计选择:事实上,DLL 和使用它的其他模块(例如 EXE由您的 DLL 客户端构建)必须使用 相同 C++ 编译器版本构建并链接到 CRT DLL 的 相同 风格。
更好的设计选择是使用 纯 C 接口导出 DLL(实现 可以使用 C++,但您应该将public API 使其成为 C),或使用 COM-like 导出 C++ 抽象接口 的方法,如建议 this CodeProject article.
假设您知道这一点,您应该能够删除以下行:
template class __declspec(dllexport) std::allocator<std::wstring>; template class __declspec(dllexport) std::vector<std::wstring>;
并且只导出承载您的 STL 数据成员的结构,例如:
MyLib.h
#pragma once
#ifndef MYLIB_API
#define MYLIB_API __declspec(dllimport)
#endif
#include <string>
#include <vector>
struct MYLIB_API MyLib_Data
{
std::vector<std::wstring> Strings;
// ... other stuff ...
};
MyLib.cpp
#define MYLIB_API __declspec(dllexport)
#include "MyLib.h"
// ... Implementation code ...
请注意,您可能会收到一条警告 C4251,类似于:
'MyLib_Data::Strings' : class 'std::vector<std::wstring,std::allocator<_Ty>>' needs to have dll-interface to be used by clients of struct 'MyLib_Data'
但你可以忽略它。