Хорошо, я прочитал несколько вопросов и статей по этой теме, и мне кажется, что я понимаю основы, но я м. все еще проблемы.
У меня есть библиотека DLL, которая экспортирует класс, членом которого является std :: string. Моя основная программа содержит классы, в которых также есть строки, и использует DLL.
Если я компилирую DLL в VS2010, я получаю следующие предупреждения:
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 в котором рассказывается, как экспортировать шаблон STL из библиотеки DLL, чтобы удовлетворить получаемые мной предупреждения.
Проблема в том, что я добавляю следующие строки для удаления предупреждений:
EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator;
EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits, std::allocator >;
DLL компилируется без предупреждений, но когда я компилирую свой EXE-файл, компоновщик срабатывает:
2>SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: __thiscall std::basic_string,class std::allocator >::~basic_string,class std::allocator >(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,class std::allocator >::size(void)const " (?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ) already defined in OtherClass.obj
И DLL, и EXE скомпилированы с теми же параметрами генерации кода. Я могу использовать МП на обоих или на MD, и результаты будут одинаковыми.
Я включаю код из свернутой программы-примера на тот случай, если я что-то пропустил выше.
Мой главный вопрос: могу ли я исправить ошибки LNK2005, или можно просто игнорировать предупреждения C4251?
Изменить: Итак, я прочитал немного больше, и похоже, что std: : строка, которую использует класс DLL, является частной переменной, к которой имеют доступ только функции-члены, можно безопасно игнорировать предупреждение ... Есть какие-либо комментарии по этому поводу? Это шаг в правильном направлении?
Код DLL:
#pragma once
#include
#include
#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;
//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, std::allocator >;
#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
#include "SampleDLL.h"
using namespace std;
void main()
{
MyClass class1;
cout << class1.getData() << endl;
}