从DLL导出C ++类

时间:2010-07-08 18:01:37

标签: c++ dllexport

我遇到了代码项目中的这个article,它讨论了使用抽象接口作为从C ++ DLL导出整个类的替代方法,以避免名称错位问题。作者在他的接口定义中有一个Release()方法,用户应该在调用后使用它来释放类对象的资源。为了自动调用此方法,作者还创建了一个类似std::auto_ptr<T>的类,在删除对象之前调用Release()方法。

我想知道以下方法是否会起作用:

#include <memory>

#if defined(XYZLIBRARY_EXPORT) // inside DLL
#   define XYZAPI   __declspec(dllexport)
#else // outside DLL
#   define XYZAPI   __declspec(dllimport)
#endif  // XYZLIBRARY_EXPORT

// The abstract interface for Xyz object.
// No extra specifiers required.
struct IXyz
{
    virtual int Foo(int n) = 0;

    //No Release() method, sub-class' destructor does cleanup
    //virtual void Release() = 0;

    virtual ~IXyz() {}
};

// Factory function that creates instances of the Xyz object.
// Private function, do not use directly
extern "C" XYZAPI IXyz* __stdcall GetXyz_();

#define GetXyz()      std::auto_ptr<IXyz>( GetXyz_() )

当然,GetXyz()可以是标题中定义的全局函数,而不是#define。这种方法的优点是我们不需要编制调用auto_ptr方法的Release()衍生物。

感谢您的回答, 与Ashish。

3 个答案:

答案 0 :(得分:3)

通过这样做,你可能会冒险在一个对象上调用delete(在你的进程中,在auto_ptr的析构函数中),该对象不是由对new()的匹配调用创建的(这是在工厂函数内完成的,因此在dll中)。例如,在调试模式下调用进程时,在发布模式下编译dll时,会遇到麻烦。

Release()方法更好。

答案 1 :(得分:2)

这正是COM的工作原理。如果已经定位Win32 API,则避免重新发明此轮。使用智能指针存储COM接口指针在Windows编程中非常常见,它们的析构函数调用Release()方法。查看_com_ptr_t和CComPtr的MSDN文档以获取创意。

答案 2 :(得分:1)

如果这是一个公共API,您面临的限制是不同模块将链接的CRT,并且创建该对象的CRT也需要是要删除它的CRT。

如果你没有选择合适的CRT,会有一团糟 任何共享内存管理的东西都应该使用CRT(或其他内存分配)作为外部库 - 即。 MSVC:多线程DLL(/ MD)

鉴于此,甚至不需要子类来实现您的目的。