最近,我一直在考虑将对象通过c ++中的dll边界传递的问题。我发现了许多具有优点和缺点的解决方案。我对他们不满意,所以花了一些时间思考如何解决这个问题。最后,我想到了这个解决方案。你怎么看待这件事?它可以防止所有可能的威胁并鼓励良好的设计吗?
编辑。威胁是指此问题的标记答案中列出的问题:
How do I safely pass objects, especially STL objects, to and from a DLL?
据我了解,它应该绕过所有问题,这些问题包括使用静态cruntime,使用对象通过dll边界传递,使用不同的编译器编译dll和exe。穿过dll边界的唯一一件事是对象指针和函数地址,据我所知,它们是安全的。内联创建shared_ptr可以确保shared_ptr的布局来自客户端模块。但是创建和销毁的代码在dll.cpp中,因此它将在dll模块中发生。
当然,命名函数“ doNotUse”并不是使人们...不使用您的函数的完美解决方案,但是如果我们坚持使用C接口,我将看不到如何避免这种情况(c ++将使我们能够使用私人/受保护的访问关键字)。
dll.h
#ifdef DLL_EXPORTS
#define EXPORT_OR_IMPORT __declspec(dllexport)
#else
#define EXPORT_OR_IMPORT __declspec(dllimport)
#endif
#include <memory>
class theInterface
{
public:
virtual void print() = 0;
virtual ~theInterface();
};
extern "C" {
EXPORT_OR_IMPORT theInterface* doNotUseThisFunction_create(/* arguments*/);
EXPORT_OR_IMPORT void doNotUseThisFunction_destroy(void* object);
}
inline std::shared_ptr<theInterface> getObject(/*argument*/)
{
return std::shared_ptr<theInterface>(doNotUseThisFunction_create(/*arguments*/), doNotUseThisFunction_destroy);
}
dll.cpp
#include "dll.h"
#include <string>
class theObject : public theInterface
{
public:
theObject();
~theObject() override;
void print() override;
private:
std::string someMemberWithMemoryAllocationOnHeap;
};
// (function definitions to make it compile)
theInterface* doNotUseThisFunction_create(/* arguments*/)
{
return new theObject();
}
void doNotUseThisFunction_destroy(void* object)
{
delete reinterpret_cast<theInterface*>(object);
}