我正在尝试将我的库导出为DLL,但是我为一个使用std :: vector的特定类获得了很多这些警告:
template <typename T>
class AGUI_CORE_DECLSPEC AguiEvent {
typedef void (*AguiCallbackFptr)(T arg, AguiWidget* sender);
std::vector<AguiCallbackFptr> events;
public:
void call(AguiWidget* sender, T arg) const;
void addHandler(AguiCallbackFptr proc);
void removeHandler(AguiCallbackFptr proc);
void removeHandler();
AguiEvent();
};
Run Code Online (Sandbox Code Playgroud)
我得到这样的警告:
警告57警告C4251:'AguiEvent :: events':类'std :: vector <_Ty>'需要让dll接口供'AguiEvent'类的客户端使用
我试图找到如何正确地做到这一点,但MSDN的文档非常适合Windows,我需要这是跨平台的,这样它只能在实际定义AGUI_CORE_DECLSPEC时执行MS特定的东西.
我该怎么做才能摆脱这些警告?
谢谢
我正在将基于ATL的静态库转换为DLL,并且在使用ATL CString类(在atlstr.h中找到)的任何导出类上收到以下警告:
警告C4251:'Foo :: str_':类'ATL :: CStringT'需要让dll接口被'Foo'类的客户端使用
我正确地声明Foo该类是通过导出的__declspec(dllexport).这是一个我可以放心忽视的警告,还是我做错了什么?DLL项目设置被设置为与ATL动态链接,但这似乎没有任何区别.
例如:
#ifdef DLLTEST_EXPORTS
#define DLLTEST_API __declspec(dllexport)
#else
#define DLLTEST_API __declspec(dllimport)
#endif
// This class is exported from the DLLTest.dll
class DLLTEST_API Foo
{
public:
Foo();
CString str_; // WARNING C4251 HERE
};
Run Code Online (Sandbox Code Playgroud)
此DLL的所有客户端也将使用ATL.
这不是一个突破性的问题,但我喜欢从警告中清除我的代码,所以这让我很紧张.
我一直在使用c ++ 11版本的pimpl成语以通常的方式隐藏我的库的类实现.
// dll header
class FrameworkImpl;
class EXPORT_API Framework
{
Framework(const Framework&) = delete;
Framework& operator=(const Framework&) = delete;
Framework(Framework&&) = delete;
Framework& operator=(Framework&&) = delete;
public:
Framework();
~Framework();
private:
std::unique_ptr<FrameworkImpl> impl_;
};
// application implementation
int main()
{
std::unique_ptr<Framework> test = std::make_unique<Framework>();
}
Run Code Online (Sandbox Code Playgroud)
一切都会好的,但我会继续收到警告:
warning C4251: 'Framework::impl_': class 'std::unique_ptr<FrameworkImpl,std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'Framework'
Run Code Online (Sandbox Code Playgroud)
所以我试着添加:
template class EXPORT_API std::unique_ptr<FrameworkImpl>;
Run Code Online (Sandbox Code Playgroud)
在前向声明之前,警告只会改为:
warning C4251: 'std::_Unique_ptr_base<_Ty,_Dx>::_Mypair': class 'std::_Compressed_pair<_Dx,FrameworkImpl *,true>' needs to have …Run Code Online (Sandbox Code Playgroud) 我有一个很好的库来管理需要返回特定字符串列表的文件.因为我将要使用它的唯一代码是C++(和Java,但是通过JNI使用C++)我决定使用标准库中的vector.库函数看起来有点像这样(其中FILE_MANAGER_EXPORT是平台定义的导出要求):
extern "C" FILE_MANAGER_EXPORT void get_all_files(vector<string> &files)
{
files.clear();
for (vector<file_struct>::iterator i = file_structs.begin(); i != file_structs.end(); ++i)
{
files.push_back(i->full_path);
}
}
Run Code Online (Sandbox Code Playgroud)
我使用向量作为参考而不是返回值的原因是试图保持内存分配的合理性,因为我真的不高兴我在c ++返回类型周围有外部"C"(谁知道为什么,我的理解是所有extern" C"确实可以防止编译器中的名称损坏.无论如何,与其他c ++一起使用的代码通常如下:
#if defined _WIN32
#include <Windows.h>
#define GET_METHOD GetProcAddress
#define OPEN_LIBRARY(X) LoadLibrary((LPCSTR)X)
#define LIBRARY_POINTER_TYPE HMODULE
#define CLOSE_LIBRARY FreeLibrary
#else
#include <dlfcn.h>
#define GET_METHOD dlsym
#define OPEN_LIBRARY(X) dlopen(X, RTLD_NOW)
#define LIBRARY_POINTER_TYPE void*
#define CLOSE_LIBRARY dlclose
#endif
typedef void (*GetAllFilesType)(vector<string> &files);
int main(int argc, char **argv)
{
LIBRARY_POINTER_TYPE manager = LOAD_LIBRARY("library.dll"); //Just an example, actual name is …Run Code Online (Sandbox Code Playgroud) 我有两个dll导出的类A和B.一个声明包含一个在其签名中使用std :: vector的函数,如:
class EXPORT A{
// ...
std::vector<B> myFunction(std::vector<B> const &input);
};
Run Code Online (Sandbox Code Playgroud)
(EXPORT是相应的通用宏_dllspec(dllexport)/ _declspec(dllimport).)
阅读有关在DLL接口中使用STL类的相关问题,我总结一下:
在DLL接口中使用std :: vector将要求使用相同编译器的相同版本编译该DLL的所有客户端,因为STL容器不是二进制兼容的.更糟糕的是,取决于客户端与其他DLL一起使用该DLL,''不稳定''DLL API可以在安装系统更新时破坏这些客户端应用程序(例如Microsoft KB软件包)(真的吗?).
尽管如此,如果需要,std :: vector可以通过导出来在DLL API中使用std::vector<B>:
template class EXPORT std::allocator<B>;
template class EXPORT std::vector<B>;
Run Code Online (Sandbox Code Playgroud)
但是,当人们想要使用std :: vector作为A(http://support.microsoft.com/kb/168958)的成员时,通常会在上下文中提到这一点.
以下Microsoft支持文章讨论了如何通过可执行文件中的指针或引用访问DLL中创建的std :: vector对象(http://support.microsoft.com/default.aspx?scid=kb;EN-US; Q172396).上述使用的解决方案template class EXPORT ...似乎也适用.然而,在第一个要点下总结的缺点似乎仍然存在.
要完全摆脱这个问题,需要包装std :: vector并更改myFunctionPIMPL等的签名.
我的问题是:
以上摘要是正确的,还是我在这里想念一些必要的东西?
为什么我的类'A'的编译没有生成警告C4251(类'std :: vector <_Ty>'需要让dll-interface被...的客户端使用)?我没有关闭编译器警告,并且myFunction在导出的A类(使用VS2005)中使用std :: vector in时没有任何警告.
myFunction在A中正确导出需要做什么?是否可以直接导出std::vector<B>和B的分配器?
返回std :: vector by-value有什么含义?假设客户端可执行文件已使用不同的编译器(-version)编译.在复制向量的情况下返回by-value时是否仍然存在问题?我猜是.类似地,将std :: vector作为常量引用传递:可以访问std::vector<B>(可能由使用不同编译器(-version)编译的可执行文件构造)导致内部麻烦 …
我将代码片段分成了一个,DLL因为它会经常更新,这样就可以更容易部署.
但我对我能做什么以及我不能做什么有疑问DLL.
std:string或CString一个DLL?structwith std::string members并将其填入DLL?DLL返回指向那里分配的结构的指针吗?它会有效吗?我可以删除吗?std::String或a Cstring?谢谢 !
好的,所以我已经阅读了几个关于这个主题的问题和文章,我觉得我理解基础知识,但我仍然遇到麻烦.
我有一个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'
Run Code Online (Sandbox Code Playgroud)
当我编译EXE时,我得到相同的警告,但没有错误,程序编译并运行.实际上,这是一个大项目,所以我得到了40个警告,我不太热衷于此.(作为侧面观察,使用VS2008编译时不会出现这些警告)
所以,我读到了这个警告,它引导我阅读这篇MS文章:http: //support.microsoft.com/default.aspx? scid = KB; EN-US; 168958,它告诉我如何从一个STL模板导出DLL来满足我得到的警告.
问题是,当我添加以下行以删除警告时:
EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator<char>;
EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string< char, std::char_traits<char>, std::allocator<char> >;
Run Code Online (Sandbox Code Playgroud)
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 " …Run Code Online (Sandbox Code Playgroud) 这是我在这个小组中的第一篇文章.
我正在创建一个DLL并在应用程序的主文件中调用它.代码编译正常,但我收到以下错误:
warning C4251: 'PNCBaseClass::m_vAvailChannelsFromRx' : class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'PNCBaseClass'
3> with
3> [
3> _Ty=int
3> ]
Run Code Online (Sandbox Code Playgroud)
我的代码如下:
#define TEST_API __declspec(dllexport)
class TEST_API PNCBaseClass
{
public:
vector<int> m_vAvailChannelsFromRx
};
Run Code Online (Sandbox Code Playgroud)
我已经找到了解决方案并尝试并失败了.
我不想禁用警告.