在dll导出函数中使用std :: vector的含义

jrg*_*jrg 16 c++ dll stl

我有两个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)编译的可执行文件构造)导致内部麻烦myFunction?我想再来一次..

  • 上面列出的最后一个要点是否真的是唯一的清洁解决方案?

非常感谢您的反馈.

das*_*ght 2

不幸的是,你的清单非常准确。其根本原因是DLL到DLL或DLL到EXE是在操作系统级别定义的,而函数之间的接口是在编译器级别定义的。在某种程度上,当客户端和服务器缺乏二进制兼容性时,您的任务与客户端-服务器交互的任务类似(尽管更容易一些)。

编译器将其所能进行的映射到 DLL 导入和导出在特定操作系统中完成的方式。由于语言规范在涉及用户定义类型甚至内置类型的二进制布局时为编译器提供了很大的自由度(回想一下, 的确切大小int取决于编译器,只要满足最小大小要求),因此导入并且需要手动从 DLL 导出以实现二进制级别的兼容性。

当您使用相同编译器的相同版本时,上面的最后一个问题不会产生问题。然而,一旦不同的编译器进入图片,所有的赌注都消失了:您需要返回到简单类型的接口,并引入包装器来在代码中维护漂亮的接口。