跨DLL边界的c++类实例化

visual Primitive C++ Class Instantiation Across DLL Boundary

本文关键字:实例化 c++ DLL 边界      更新时间:2023-10-16

我正在尝试创建一个非托管的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边界实现此功能?通过这样做,我对用户施加了什么限制?

不,不安全。由于不同编译器的c++ abi不一定兼容,因此不能在不同编译器编译的单元之间传递c++对象。

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

这就是Visual Basic如何实例化和调用用任意语言实现的类的方法,只要该语言支持COM绑定。

虽然COM是由Microsoft引入的,但这并不意味着您可以将您的项目移植到使用他们的任何特定产品或库。你"只"需要设置一些基本函数(QueryInterface, AddRef, Release等)。如果您是新手,这并不简单,但这是一种有效的解决方案,并且该技术值得学习。