问题
I have a dll (my_library.dll
) that exports a struct using __declspec(dllexport)
. Since this struct contains an std::vector<std::wstring> member
, I've also exported functions for it like so:
template class __declspec(dllexport) std::allocator<std::wstring>;
template class __declspec(dllexport) std::vector<std::wstring>;
Please note that I've defined macros such that dll exports above struct and vector when compiling and they are imported (via __declspec(dllimport))
when the dll is being used by another application.
The above dll builds fine.
Now this my_library.dll (and the corresponding my_library.lib
) is linked to an exe (my_exe.exe
). This exe has a .cpp file (exe_source.cpp
) that defines a global std::vector<std::wstring>
variable. This source file compiles fine.
However when building this exe, I get the following error:
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
What I suspect is that the my_library.dll has all std::vector<std::wstring>
functions defined and exported, and using the global std::vector<std::wstring>
variable in the exe_source.cpp
is also resulting in definition of many std::vector<std::wstring>
functions, leading to linker complaining that multiple definitions of such functions are found.
Am I understanding the error correctly?
And how to fix this?
Thanks for your time.
回答1:
First, having STL classes at DLL interfaces is a highly constraining design choice: in fact, both the DLL and the other modules using it (e.g. the EXE built by your DLL clients) must be built with the same C++ compiler version and linking to the same flavor of the CRT DLL.
Better design choices would be exporting a DLL with a pure C interface (the implementation can use C++, but you should flatten the public API to make it C), or use a COM-like approach of exporting C++ abstract interfaces, as suggested in this CodeProject article.
Assuming you are aware of that, you should be able to remove the lines:
template class __declspec(dllexport) std::allocator<std::wstring>; template class __declspec(dllexport) std::vector<std::wstring>;
and just export the structure hosting your STL data members, for example:
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 ...
Note that you may receive a warning C4251, something like:
'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'
but you may ignore it.
来源:https://stackoverflow.com/questions/33800727/linking-errors-while-exporting-stdvector-from-dll