Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在dll接口或ABI中使用标准库(STL)类?_C++_Dll_C++11_Stl_Std - Fatal编程技术网

C++ 如何在dll接口或ABI中使用标准库(STL)类?

C++ 如何在dll接口或ABI中使用标准库(STL)类?,c++,dll,c++11,stl,std,C++,Dll,C++11,Stl,Std,在导出包含与visual studio警告C4251相关的stl类之前,存在一些问题:例如,此问题或此问题。 我已经在UnknownRoad上读了这篇精彩的解释 盲目地禁用警告似乎有点危险,尽管这可能是一种选择。包装所有这些std类并导出它们也不是一个真正的选项。它毕竟被称为标准模板库。。。也就是说,我们希望提供一个与这些标准类的接口 如何在dll接口中使用stl类?常见做法是什么?在进一步阅读之前,请记住一件事:我的答案来自于编写可移植代码的观点,这些代码可以在由在不同编译器下编译的模块组成的

在导出包含与visual studio警告C4251相关的stl类之前,存在一些问题:例如,此问题或此问题。 我已经在UnknownRoad上读了这篇精彩的解释

盲目地禁用警告似乎有点危险,尽管这可能是一种选择。包装所有这些std类并导出它们也不是一个真正的选项。它毕竟被称为标准模板库。。。也就是说,我们希望提供一个与这些标准类的接口


如何在dll接口中使用stl类?常见做法是什么?

在进一步阅读之前,请记住一件事:我的答案来自于编写可移植代码的观点,这些代码可以在由在不同编译器下编译的模块组成的应用程序中使用。这可能包括同一编译器的不同版本,甚至不同的补丁级别

如何在我的应用程序中使用stl类 dll接口

回答:你经常做不到

原因:STL是一个代码库,而不是像DLL那样的二进制库。它没有一个单一的ABI可以保证在您可能使用它的任何地方都是相同的。事实上,STL确实代表“标准”模板库,但除了标准之外,这里还有一个关键词是“模板”

该标准定义了每个STL类需要提供的方法和数据成员,并定义了这些方法的作用;但是没有了。特别是,该标准没有规定编译器编写器应该如何实现标准定义的功能。编译器编写者可以自由提供STL类的实现,该类添加标准中未列出的成员函数和成员变量,只要标准中定义的成员仍然存在并且按照标准的要求执行

也许可以举个例子。标准中将
basic_string
类定义为具有某些成员函数和变量。标准中的实际定义几乎有4页,但这里只是其中的一个片段:

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
  public:
    // 21.3.3 capacity:
    size_type size() const;
    size_type length() const;
    size_type max_size() const;
    void resize(size_type n, charT c);
    void resize(size_type n);
    size_type capacity() const;
    void reserve(size_type res_arg = 0);
    void clear();
    bool empty() const;
[snip]
};
…而带有SP1的MSVC 10可能如下所示:

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
char* m_pTheString;
};

size_t basic_string::size() const { return strlen(m_pTheString;) }
namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
vector<char> m_TheString;
};

size_t basic_string::size() const { return m_TheString.size(); }
(MyGizmo)的大小是多少

假设我在上面提出的实现,在MSVC10下它将是
sizeof(char*)
,但在SP1下它将是
sizeof(vector)
。如果您在VC10 SP1中编写一个使用DLL的应用程序,那么对象的大小看起来将与实际大小不同。二进制接口已更改


关于这一点的另一种处理方法,请参见《C++编码标准》(Amazon)第63期


1:“您通常无法”当您完全控制工具链和库时,您实际上可以以相当高的可靠性导出标准库组件或任何其他代码库组件(如Boost)


基本问题是,对于源代码库,不同编译器和库的不同版本之间的大小和定义可能不同。如果您在一个环境中工作,无论您的代码在哪里使用,您都可以控制这两个方面,那么您可能不会有问题。例如,在一家贸易公司,所有的系统都是在内部编写的,只在内部使用,这样做是可能的。

答案是不要。我们稍后将尝试详细说明。当我们不能安全地使用标准模板库设计API时,拥有标准模板库有什么意义?STL并不是为了解决这个问题而设计的。事实上,标准没有提到API、DLL或类似的东西。感谢John的精彩解释。我理解ABI不在标准中。用一个编译器构建所有lib就足够了吗?还是应该将所有stl成员变量放在pimpl指针后面?@Andre:是的,用同一个编译器构建所有内容就足够了。当我说“在进一步阅读之前,请记住一件事…”时,我暗示了这一点,那么头部实现呢?我可以在头实现中使用STL吗?毕竟,代码是在客户端包含和编译的。@Fabian如果您的头实现只将STL数据传递给您的客户端代码,而不是您自己的非头代码,那么应该可以。
class MyGizmo
{
public:
  std::string name_;
};