【发布时间】:2015-11-12 08:07:26
【问题描述】:
我多次读过,在 DLL 边界之外传递向量和字符串等 STL 对象是不好的做法,因为不同的编译器版本可以为 STL 对象生成不同的代码。因此,您应该设计一个 C 风格的接口,并且根本不传递 STL 对象。但是,我仍然有一些不清楚的地方:
1. DLL 的“边界”是什么?
是否正确地说,边界是代码在 DLL 端被 编译 的地方?如果我在 DLL 中定义一个 .h 文件(例如编写工厂类)并在不同的项目中使用该头文件怎么办?那个 .h 文件是在 DLL 的边界之内还是之外,为什么?
2。 DLL 中包含什么?
假设我有一个类 Foo:
class Foo
{
public:
__declspec(dllexport) void f1(); //instantiates v1 inside function
private:
unique_ptr<vector<int>> v1 = nullptr;
}
如果我只用 __declspec(dllexport) 标记函数 f1(),则只有这个函数应该包含在 DLL 中。如果 DLL 中不包含 v1,f1() 中的代码如何知道 v1 是什么?
3.使用 unique_ptr 将对象传递出 DLL 边界
我几乎每次在我的项目中都使用 unique_ptr。据我了解,从 DLL 返回 unique_ptr 是不好的做法,因为 unique_ptr 是一个 STL 对象。如何在 DLL 中实例化一个对象并返回一个 unique_ptr 给它?
4.为什么定义接口或使用 PIMPL 有助于定义 DLL 接口?
我仍然需要将我的 STL 类转换为 C 风格的对象。在使用 DLL 的项目中,我不得不以某种方式再次将 C 风格的对象包装在 STL 类中。在这种情况下,我看不到使用接口或 PIMPL 的任何优势。 另外,如果我定义一个接口(具有纯虚函数的类),这与在我的类中使用 __declspec(dllexport) 声明函数的效果不一样吗?
class IFoo
{
public:
virtual ~IFoo() = 0 {};
virtual void f1() = 0;
}
class Foo : public IFoo
{
public:
void f1();
//__declspec(dllexport) void f1(); //why use an interface if I can just declare the functions like this?
}
如何在现代 C++ 11/14 库中解决 DLL-STL 问题?是否有任何现代开源库可供我查看?
【问题讨论】:
-
On 选项当然不是混合编译器版本或为每个支持的编译器构建单独的库。 Boost does that
-
这可能是最简单的解决方案,我正在考虑这样做,因为确保可移植 DLL 似乎是一场真正的斗争。一般来说,这对于商业项目也可以接受吗?