导出 C++来自 DLL 的类
我在代码项目上发现了这篇文章,其中讨论了使用摘要接口作为从 C++ DLL 导出整个类的替代方案,以避免名称损坏问题。作者在其接口定义中有一个 Release()
方法,用户应该在使用类对象后调用该方法来释放该类对象的资源。为了自动调用此方法,作者还创建了一个类似 std::auto_ptr
的类,该类在删除对象之前调用 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
。此方法的优点是我们不需要编写自己的调用 Release()
方法的 auto_ptr
派生类。
感谢您的回答, 阿什什。
I came across this article on Code Project that talks about using an abstract interface as an alternative to exporting an entire class from a C++ DLL to avoid name mangling issues. The author has a Release()
method in his interface definition that is supposed to be called by the user to free the class object's resources after using it. To automate the calling of this method the author also creates an std::auto_ptr<T>
-like class that calls the Release()
method before deleting the object.
I was wondering whether the following approach would work instead:
#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_() )
Of course, GetXyz()
can be a global function defined in the header instead of a #define
. The advantage to this method would be that we don't need to cook up our own derivative of auto_ptr
that calls the Release()
method.
Thanks for your answers,
Ashish.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
通过这样做,您可能会冒着调用delete(在您的进程中,在auto_ptr的析构函数中)的风险,该对象不是通过对new()的匹配调用创建的(这是在工厂函数内部完成的,因此是在dll内部完成的)。肯定会出现问题,例如当您的 dll 在发布模式下编译而调用进程在调试模式下时。
Release() 方法更好。
by doing this, you risk calling delete (in your process, within auto_ptr's destructor) on an object that is not created by the matching call to new() (that is done inside the factory function, hence inside the dll). Trouble guaranteed, for instance when your dll is compiled in release mode while the calling process in debug mode.
The Release() method is better.
这正是 COM 的工作原理。如果您已经针对 Win32 API,请避免重新发明这个轮子。使用智能指针存储COM接口指针在Windows编程中很常见,它们的析构函数调用Release()方法。查看 _com_ptr_t 和 CComPtr 的 MSDN 文档以获取想法。
This is exactly how COM works. Avoiding re-inventing this wheel if you already target the Win32 API. Using smart pointers to store COM interface pointers is very common in Windows programming, their destructor calls the Release() method. Take a peek at the MSDN docs for _com_ptr_t and CComPtr for ideas.
如果这是一个公共 API,您面临的限制是不同模块将链接到的 CRT,并且创建该对象的 CRT 也必须是删除该对象的 CRT。
如果你没有选择正确的CRT,将会出现混乱
任何共享内存管理的东西都应该使用 CRT(或其他内存分配)作为外部库 - 即。 MSVC:多线程 DLL (/MD)
鉴于此,甚至不需要子类来实现您的目的。
The restriction you face if this is a public API is the CRT that the different modules will be linked against and that the CRT that creates the object also needs to be the one to delete it.
There will be a mess if you don't choose the right CRT
Anything sharing memory management should use CRT (or other memory allocation) as external lib - ie. MSVC: Multi-threaded DLL (/MD)
Given that, then there is not even a need for the subclass to achieve your purpose.