8

我有一个 DLL,它需要访问存储在主机应用程序的 STL 容器中的数据。因为 C++ 没有标准的 ABI,而且我想支持不同的编译器,所以应用程序和 DLL 之间的接口基本上必须保持纯旧数据。

对于向量,这相对简单。您可以简单地返回向量的内存块,因为它保证是连续的:

// To return vector<int> data
virtual void GetVectorData(const int*& ptr, size_t& count) const
{
    if (!vec.empty())
        ptr = &(vec.front());

    count = vec.size();
}

现在,DLL 可以通过该接口对向量数据进行安全的只读访问。DLL 也可以包装它以将内容复制到自己的向量中。

但是 STL 列表(和双端队列)呢?是否有另一种直接的方法允许通过 DLL 边界进行访问?还是我必须求助于某种 GetFirst()/GetNext() 接口?我可能需要对很多列表执行此操作,因此最好有一个像矢量这样简单的解决方案。

4

3 回答 3

10

如果您在实例化每个 stl 类型的位置小心,您可以在 DLL 之间传递 stl 对象并支持不同的编译器。您需要一些智能的“DLLEXPORT”宏——我使用以下设置成功支持 VC 和 gcc。

#ifdef WIN32
#ifdef MYDLLLIB_EXPORTS      // DLL export macros
#define MYDLLLIB_API __declspec(dllexport)
#define MYDLLLIB_TEMPLATE
#else
#define MYDLLLIB_API __declspec(dllimport)
#define MYDLLLIB_TEMPLATE extern
#endif
#else                       // Not windows --- probably *nix/bsd
#define MYDLLLIB_API
#ifdef MYDLLLIB_EXPORTS
#define MYDLLLIB_TEMPLATE
#else
#define MYDLLLIB_TEMPLATE extern
#endif
#endif // WIN32

编译 DLL 时,定义 MYDLLLIB_EXPORTS。然后,您可以在 DLL 中实例化您希望使用的每种 stl 类型,例如,字符串的列表或向量

MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::vector<std::string>;
MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::list<std::string>;

然后,您的 DLL 的使用者(没有定义 MYDLLLIB_EXPORTS)将看到

extern template class __declspec(dllimport) std::vector<std::string>;

并使用从您的 DLL 导出的二进制代码,而不是实例化自己的。

于 2009-12-11T09:49:47.683 回答
7

也许您可以将“句柄”之类的东西传递给列表/双端队列迭代器?这些句柄类型将是不透明的,并在您将发送给用户的头文件中声明。在内部,您需要将句柄值映射到列表/双端队列迭代器。基本上,用户会编写如下代码:

ListHandle lhi = GetListDataBegin();
const ListHandle lhe = GetListDataEnd();

while (lhi != lhe)
{
  int value = GetListItem(lhi);
  ...
  lhi = GetNextListItem(lhi);
}
于 2009-12-10T15:23:39.083 回答
1

应用程序和 DLL 之间的接口基本上必须保持纯旧数据。

不必要。您必须确保使用相同的编译器版本。此外,影响 STL 对象布局的构建设置在 dll 和应用程序之间完全相同。

如果您要将 dll 释放到野外,那么您应该关注跨 dll 边界暴露 STL。但是,如果一切都在您的控制之下并且纯粹是内部的(或者如果您可以严格执行 3rd 方构建设置/编译器),那么您应该没问题。

于 2009-12-10T15:00:30.743 回答