Linking errors while exporting std::vector from dll

邮差的信 提交于 2021-01-28 04:55:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!