代码之家  ›  专栏  ›  技术社区  ›  Praetorian Luchian Grigore

从DLL导出C++类

  •  1
  • Praetorian Luchian Grigore  · 技术社区  · 15 年前

    我遇到了这个 article 在代码项目中,讨论使用抽象接口作为从C++ DLL导出整个类以避免名称篡改问题的替代方案。作者有一个 Release() 方法,该方法应该由用户调用,以便在使用类对象后释放该类对象的资源。为了自动调用这个方法,作者还创建了一个 std::auto_ptr<T> -就像一个叫 方法删除对象。

    我想知道以下方法是否会奏效:

    #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 这就叫 方法。

    阿希什。

    3 回复  |  直到 15 年前
        1
  •  3
  •   stijn    15 年前

    这样做,您就有可能对一个对象调用delete(在您的过程中,在auto\ptr的析构函数中),而该对象不是通过对new()的匹配调用创建的(这是在factory函数中完成的,因此是在dll中完成的)。故障保证,例如当您的dll是在发布模式下编译,而调用进程在调试模式下。

    Release()方法更好。

        2
  •  2
  •   Hans Passant    15 年前

    这正是COM的工作原理。如果您已经以Win32 API为目标,请避免重新发明此控制盘。使用智能指针存储COM接口指针在Windows编程中非常常见,它们的析构函数调用Release()方法。浏览一下MSDN文档,了解更多信息和想法。

        3
  •  1
  •   Greg Domjan    15 年前

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

    如果你不选择正确的阴极射线管,那将会是一片混乱

    既然如此,那么子类甚至不需要实现您的目的。