17

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.

4

2 回答 2

2

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

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

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

于 2012-05-13T16:26:06.607 回答
0

我一直有同样的问题,并发现了一个巧妙的解决方案。您可以从库中传递 a
而不是传递。 然后你引用的问题在库中处理,你根本不需要处理它。 当然,代价是不得不使用该库并接受其稍差的性能。 就它为您节省的编码和调试时间而言,这个解决方案非常值得。std:vectorQVectorQt
Qt

于 2012-11-05T09:57:46.400 回答