在dll导出函数中使用std :: vector的启示 [英] Implications of using std::vector in a dll exported function

查看:415
本文介绍了在dll导出函数中使用std :: vector的启示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个dll导出的类A和B. A的声明包含一个函数,在其签名中使用std :: vector:

  class EXPORT A {
// ...
std :: vector< B> myFunction(std :: vector< B> const& input);
};

(EXPORT是通常的宏放置_ declspec(dllexport) em> _declspec(dllimport)。)



阅读关于在DLL接口中使用STL类的问题,我总结一下:




  • 在DLL接口中使用std :: vector会要求该DLL的所有客户端都使用相同的版本同一个编译器因为STL容器不是二进制兼容的。更糟糕的是,根据客户端与其他DLL的使用情况,instableDLL API可能在安装系统更新(例如Microsoft KB软件包)时破坏这些客户端应用程序(真的?)。


  • 尽管如此,如果需要,std :: vector可以通过导出 std :: vector< B> like:

     模板类EXPORT std :: allocator< B& 
    template class EXPORT std :: vector< B> ;;

    虽然,这通常在上下文中提到,当一个人想使用std :: vector作为<


  • 以下Microsoft支持文章讨论了如何通过可执行文件中的指针或引用访问在DLL中创建的std :: vector对象(http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q172396)。上面的使用模板类EXPORT ... 的解决方案似乎也适用。


  • 要完全摆脱这个问题,需要将std :: vector和更改 myFunction ,PIMPL等的签名。




我的问题是:




  • 上述摘要是否正确, >

  • 为什么编译我的类'A'不产生警告C4251(类'std :: vector< _Ty>'需要有dll-接口供客户端使用...] )?我没有关闭编译器警告,我没有得到任何警告使用std :: vector在 myFunction 在导出类A(与VS2005)。


  • 在A中正确导出 myFunction 需要做什么?只是导出 std :: vector< B> 和B的分配器是可行的吗?


  • 返回std :: vector by-value的含义是什么?假设客户端可执行文件已使用不同的编译器(-version)编译。在向量被复制时返回值的情况下,问题是否仍然存在?我猜是。类似地,将std :: vector作为常量引用:可以访问 std :: vector< B> (其可以由使用不同编译器版本))导致麻烦 myFunction


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




非常感谢您的反馈。

解决方案

列表是非常突出。这样做的根本原因是DLL-to-DLL或DLL-to-EXE在操作系统的级别上定义,而函数之间的接口在编译器的级别上定义。在某种程度上,当客户端和服务器缺乏二进制兼容性时,您的任务与客户端 - 服务器交互类似(尽管稍微容易一些)。



它可以在特定操作系统中完成DLL导入和导出的方式。因为语言规范给编译器提供了很多自由,当涉及到用户定义类型的二进制布局,有时甚至内置类型(回忆, int 的确切大小是编译器 - 依赖,只要满足最小的大小调整要求),从DLL导入和导出需要手动完成,以实现二进制级兼容性。



版本的同一个编译器,这最后一个问题上面没有创建一个问题。然而,一旦不同的编译器进入图片,所有的注单都关闭:你需要回到简单类型的接口,并引入包装器来维护你的代码中漂亮的接口。


I have two dll-exported classes A and B. A's declaration contains a function which uses a std::vector in its signature like:

class EXPORT A{
 // ...
 std::vector<B> myFunction(std::vector<B> const &input);
};

(EXPORT is the usual macro to put in place _declspec(dllexport)/_declspec(dllimport) accordingly.)

Reading about the issues related to using STL classes in a DLL interface, I gather in summary:

  • Using std::vector in a DLL interface would require all the clients of that DLL to be compiled with the same version of the same compiler because STL containers are not binary compatible. Even worse, depending on the use of that DLL by clients conjointly with other DLLs, the ''instable'' DLL API can break these client applications when system updates are installed (e.g. Microsoft KB packages) (really?).

  • Despite the above, if required, std::vector can be used in a DLL API by exporting std::vector<B> like:

    template class EXPORT std::allocator<B>;
    template class EXPORT std::vector<B>;
    

    though, this is usually mentioned in the context when one wants to use std::vector as a member of A (http://support.microsoft.com/kb/168958).

  • The following Microsoft Support Article discusses how to access std::vector objects created in a DLL through a pointer or reference from within the executable (http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q172396). The above solution to use template class EXPORT ... seems to be applicable too. However, the drawback summarized under the first bullet point seems to remain.

  • To completely get rid of the problem, one would need to wrap std::vector and change the signature of myFunction, PIMPL etc..

My questions are:

  • Is the above summary correct, or do I miss here something essential?

  • Why does compilation of my class 'A' not generate warning C4251 (class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of...)? I have no compiler warnings turned off and I don't get any warning on using std::vector in myFunction in exported class A (with VS2005).

  • What needs to be done to correctly export myFunction in A? Is it viable to just export std::vector<B> and B's allocator?

  • What are the implications of returning std::vector by-value? Assuming a client executable which has been compiled with a different compiler(-version). Does trouble persist when returning by-value where the vector is copied? I guess yes. Similarly for passing std::vector as a constant reference: could access to std::vector<B> (which might was constructed by an executable compiled with a different compiler(-version)) lead to trouble within myFunction? I guess yes again..

  • Is the last bullet point listed above really the only clean solution?

Many thanks in advance for your feedback.

解决方案

Unfortunately, your list is very much spot-on. The root cause of this is that DLL-to-DLL or DLL-to-EXE is defined on the level of the operating system, while the the interface between functions is defined on the level of a compiler. In a way, your task is similar (although somewhat easier) to that of client-server interaction, when the client and the server lack binary compatibility.

The compiler maps what it can to the way the DLL importing and exporting is done in a particular operating system. Since language specifications give compilers a lot of liberty when it comes to binary layout of user-defined types and sometimes even built-in types (recall that the exact size of int is compiler-dependent, as long as minimal sizing requirements are met), importing and exporting from DLLs needs to be done manually to achieve binary-level compatibility.

When you use the same version of the same compiler, this last issue above does not create a problem. However, as soon as a different compiler enters the picture, all bets are off: you need to go back to the plainly-typed interfaces, and introduce wrappers to maintain nice-looking interfaces inside your code.

这篇关于在dll导出函数中使用std :: vector的启示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆