跨DLL边界的原始C ++类实例化

时间:2015-08-20 18:24:09

标签: c++ visual-c++ dll

我正在尝试创建一个非托管C ++ DLL。在大多数情况下,我使用接口和工厂模式为用户跨DLL边界实例化复杂对象。

我的问题是关于可以在堆栈上分配的原始类类型。

例如,考虑下面的代码,我的库中有一个类和两个实用程序函数:

// Forward declaration for the PIMPL idiom
class SimpleData;

class Simple
{
public:

    AWESOME_API Simple();
    AWESOME_API Simple(const Simple& other);
    AWESOME_API Simple& operator=(const Simple& other);
    AWESOME_API ~Simple();

    AWESOME_API void PublicFunction1(); // Public function with private implementation
    AWESOME_API void PublicFunction2();
    // ...

private:

    void SecretFunction1();
    void SecretFunction2();
    // ...

private:

    int m_Number;
    SimpleData* m_Data;

    // ... Other primitive data types ...
};

AWESOME_API static void DoSomethingWithSimple(Simple& simple);
AWESOME_API static Simple GiveMeASimple();

假设AWESOME_API__declspec(dllimport) / __declspec(dllexport)属性的正确实现。

然后我可以使用这个库安全地在我的应用程序中执行以下操作,同时让用户可以自由地使用他们选择的任何编译器编译应用程序(只要它们都是32位应用程序)?

#include "Awesome/Simple.h"

int main(int argc, char* argv[])
{
    Simple s0;
    Simple s1(s0);
    Simple* s2 = new Simple();
    Simple s3 = GiveMeASimple();
    DoSomethingWithSimple(s1);
    DoSomethingWithSimple(*s2);
    delete s2;

    return 0;
}

如果没有,我如何跨DLL边界实现此功能?通过这样做,我对用户施加了哪些限制?

2 个答案:

答案 0 :(得分:0)

不,这不安全。由于不同编译器的C ++ ABI不是必然兼容的,因此您无法在使用不同编译器编译的单元之间传递C ++对象。

答案 1 :(得分:0)

为了使其工作,有问题的编译器需要就类布局的外观达成二进制级别。我建议你阅读一下COM中实现的方法 - 这是定义一个抽象接口(基本上是一个vtbl,即函数指针列表),并确保编译器对此达成一致。

这就是说,例如,Visual Basic可以实例化并调用以任意语言实现的类的方法,前提是该语言支持COM绑定。

虽然COM是由Microsoft引入的,但这并不意味着您已将项目移植到使用他们的任何特定产品或库。您“只需”设置一些基本功能(QueryInterface,AddRef,Release等)。如果你是新手,这不是微不足道的,但它是一个有效的解决方案,这项技术值得学习。