在 dll 接口中使用 shared_ptr [英] Using shared_ptr in dll-interfaces

查看:33
本文介绍了在 dll 接口中使用 shared_ptr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 dll 中有一个抽象类.

I have an abstract class in my dll.

class IBase {
  protected:
       virtual ~IBase() = 0;
  public:
       virtual void f() = 0;
};

我想在加载 dll 的 exe 文件中获取 IBase.第一种方法是创建以下函数

I want to get IBase in my exe-file which loads dll. First way is to create following function

IBase * CreateInterface();

并在IBase中添加虚函数Release().

第二种方法是创建另一个函数

Second way is to create another function

boost::shared_ptr<IBase> CreateInterface();

并且不需要Release()函数.

问题.

1) 在第二种情况中,析构函数和内存释放是在dll中(不是在exe文件中)调用的吗?

1) Is it true that the destructor and memory deallocation is called in the dll (not in exe-file) in the second case?

2) 如果 exe 文件和 dll 是用不同的编译器(或不同的设置)编译的,第二种情况是否能正常工作.

2) Does the second case work well if exe-file and dll was compiled with different compilers (or different settings).

推荐答案

第一个问题的答案: dll 中的虚拟析构函数被调用 - 有关其位置的信息嵌入在您的对象中(在虚表中).在内存释放的情况下,这取决于您的 IBase 用户的纪律性.如果他们知道必须调用 Release() 并考虑到异常可以以令人惊讶的方向绕过控制流,就会使用正确的方法.

An answer to your first question: The virtual destructor in your dll is called - the information about its location is embedded in your object (in the vtable). In the case of memory deallocation it depends how disciplined the users of your IBase are. If they know they have to call Release() and consider that exception can bypass the control flow in an surprising direction, the right one will be used.

但是如果 CreateInterface() 返回 shared_ptr 它可以将正确的释放函数绑定到这个智能指针.您的库可能如下所示:

But if CreateInterface() returns shared_ptr<IBase> it can bind the right deallocation function right to this smart pointer. Your library may look like this:

Destroy(IBase* p) {
    ... // whatever is needed to delete your object in the right way    
}

boost::shared_ptr<IBase> CreateInterface() {
    IBase *p = new MyConcreteBase(...);
    ...
    return shared_ptr<IBase>(p, Destroy); // bind Destroy() to the shared_ptr
}                                         // which is called instead of a plain
                                          // delete

因此,您的 DLL 的每个用户都可以轻松防止资源泄漏.他们永远不必费心调用 Release() 或注意异常绕过他们的控制流.

Thus every user of your DLL is easily prevented against resource leaks. They never have to bother about calling Release() or pay attention to exceptions bypassing surprisingly their control flow.

回答你的第二个问题:这种方法的缺点由另一个answers:您的听众必须使用与您相同的编译器、链接器、设置、库.如果它们可能很多,这可能是您的图书馆的主要缺点.您必须选择:安全与更大的受众

To answer your second question: The downside of this approach is clearly stated by the other answers: You're audience has to use the same compiler, linker, settings, libraries as you. And if they could be quite a lot this can be major drawback for your library. You have to choose: Safety vs. larger audience

但可能存在漏洞:在您的应用程序中使用 shared_ptr,即

But there's a possible loophole: Use shared_ptr<IBase>in your application, i.e.

{
    shared_ptr<IBase> p(CreateInterface(), DestroyFromLibrary);
    ...
    func();
    ...
}

因此不会跨 DLL 边界传递特定于实现的对象.尽管如此,您的指针还是安全地隐藏在 shared_ptr 后面,即使 func() 是否抛出异常,它也会在正确的时间调用 DestroyFromLibrary.

Thus no implementation specific object is passed across the DLL boundary. Nevertheless your pointer is safely hidden behind the shared_ptr, who's calling DestroyFromLibrary at the right time even if func()'s throwing an exception or not.

这篇关于在 dll 接口中使用 shared_ptr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆