c++ - 使用 C++11/14 正确定义 DLL 接口(interface)

标签 c++ c++11 dll stl c++14

我多次读到,在 DLL 边界之外传递 STL 对象(如 vector 和 string)是不好的做法,因为不同的编译器版本可以为 STL 对象生成不同的代码。因此,你应该设计一个C风格的接口(interface),根本不传递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。为什么定义接口(interface)或使用 PIMPL 有助于定义 DLL 接口(interface)?

我仍然需要将我的 STL 类转换为 C 风格的对象。在使用 DLL 的项目中,我将不得不以某种方式再次将 C 样式对象包装在 STL 类中。在这种情况下,我看不到使用接口(interface)或 PIMPL 有任何优势。 此外,如果我定义一个接口(interface)(具有纯虚函数的类),这是否与仅使用 __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 问题是如何解决的?有没有我可以看看的现代开源库?

最佳答案

不幸的是,不同编译器的 STL 类型不一致。即使是不同版本的 Visual Studio 也有差异。

边界是编译代码的地方。如果您在库的头文件中有一个实现,那么用于编译 EXE 的编译器将编译代码。这可能非常糟糕,因为 EXE 中的代码认为数据与 DLL 中的代码认为数据不同。 (您需要注意这样的差异,特别是如果您在结构定义中有 #ifs 并且您需要明确包装)。

唯一可以确定的方法是定义所有您自己的类型(注意打包)并且不使用 STL。这是 DLL 库通常做的事情。

接口(interface)可以使用户动态链接到库。使用 __declspec(dllexport) 需要静态链接;也就是说,EXE 必须链接到编译 DLL 时生成的 .lib 才能访问所有功能。这意味着除其他事项外,您无法在不重新编译 EXE 的情况下更新 DLL(可能 - 在某些情况下您可以避免这种情况,但这不是一个好主意)。

通过动态链接,只要不更改接口(interface),您就可以更新 DLL 或向 DLL 添加功能,而无需重新链接 EXE。 EXE 可能会调用 DLL 上的 LoadLibrary() 和 GetProcAddress() 以访问一个返回接口(interface)的函数。包括作为参数传递的数据类型在内的所有其他内容都是接口(interface)(即仅包含纯虚函数)或简单结构。这就是 COM 基本级别的工作方式。

关于c++ - 使用 C++11/14 正确定义 DLL 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32088478/

相关文章:

c++ - 在UnrealEngine中动态创建SphereComponent

c++ - 防止切片的惯用方法?

c++ - 用于 xml 标签内容的单一匹配的正则表达式

c - 保护开源软件可执行文件中的公司数据

c++ - 将三路比较运算符的结果与 nullptr 进行比较有什么作用?

c++ - virtual 关键字在函数声明中的位置

c++ - 当对象类型是模板参数时,有没有办法将模板参数传递给对象上的函数?

c++ - 使用 join() 从不同范围运行 C++ 线程

windows - 64 位 Windows 是否使用 KERNEL64?

c++ - 谁能用几个术语解释一下 DYNAMIC_CLASS?