加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 释放DLL创建的对象

发布时间:2020-12-16 07:06:48 所属栏目:百科 来源:网络整理
导读:我的DLL加载了LoadLibrary – 他们仍然可以共享运行时,还是我必须确保在分配的同一个DLL中删除对象? 在我的示例中,我有一个在DLL模块中实现的公共基类,然后由Lua对象镜像,Lua确定其生命周期.因此,当Lua垃圾收集器决定这样做时,我需要释放该对象,并且我无法
我的DLL加载了LoadLibrary – 他们仍然可以共享运行时,还是我必须确保在分配的同一个DLL中删除对象?

在我的示例中,我有一个在DLL模块中实现的公共基类,然后由Lua对象镜像,Lua确定其生命周期.因此,当Lua垃圾收集器决定这样做时,我需要释放该对象,并且我无法预测将从哪个DLL中进行垃圾回收.

我在想每个DLL都有以下函数的副本:

int ReleaSEObject(lua_State* L)
{
    // object pointer is stored in field [0]
    lua_rawgeti(L,-1,0);
    delete (Object*) lua_touserdata(L,-1);
    return 0;
}

然后,指向此函数的指针将放在metatable __gc字段中,metatable将用于该DLL中定义的派生类的所有实例.这足以保证安全删除吗?

解决方法

考虑在dll的客户端上使用std :: unique_ptr或std :: shared_ptr(使用自定义删除器调用ReleaSEObject),这些可以正确地处理跨dll边界删除.

另外,将dll接口完全保持为“C”是一个很好的做法,这样dll就可以使用不同的c运行时进行编译,并且名称保持不变.
不是从dll继承基类实现,而是导出BaseImpl * CreateBaseImpl();
void DeleteBaseImpl(BaseImpl *);
这对函数让它们返回一个指向你需要的实现的指针.然后该指针应该被送到您选择的智能指针.使BaseImpl的公共接口仅使用原始类型(句柄,数字,指向这样的指针,C数组 – 好; stl容器 – 不好:创建cpp运行时依赖性)

我猜它看起来像:

// code using LUA - unconcerned with the cross-dll nature of the implementation
...
{
    auto p = new ConcreteImpl(); // pass p to LUA as you normally would
    ...
    // when LUA wants it deleted:
    delete p;
    p = nullptr;
    // probably tell LUA it was deleted
}
...
// BaseImpl.h - Dll Interface  header

class BaseImpl;

extern "C" BaseImpl * CreateBaseImpl();
extern "C" void DeleteBaseImpl(BaseImpl *p);
// Client code

#include "BaseImpl.h"

#include <type_traits>
#include <memory>

#include <Windows.h>

class ConcreteImpl { // no inheritance probably necessary
{
    using namespace std;
    ...
    ConcreteImpl() 
    :   m_ptrDll( ::LoadLibraryW(L"BaseImpl.dll"),&::FreeLibrary ),m_ptrBase( nullptr,[](BaseImpl *){} )
    {
        Assert( m_ptrDll,"LoadLibraryW() failed err=0x%x",::GetLastError() );

        auto pfnCreate = reinterpret_cast<decltype(&CreateBaseImpl)>(
            ::GetProcAddress(m_ptrDll.get(),"CreateBaseImpl") );

        auto pfnDelete = reinterpret_cast<decltype(&DeleteBaseImpl)>(
            ::GetProcAddress(m_ptrDll.get(),"DeleteBaseImpl") );

        Assert( pfnCreate && pfnDelete,"GetProcAddress() failed err=0x%x",::GetLastError() );

        // use move constructor to assign new value
        m_ptrBase = decltype(m_ptrBase)( pfnCreate(),pfnDelete );

        Assert( m_ptrBase,"CreateBaseImpl returned nullptr" );
    }
    ...
    // methods that use m_ptrBase go here
    ...
    unique_ptr<
        remove_pointer<HMODULE>::type,decltype(&::Freelibrary)
    > m_ptrDll;

    unique_ptr<BaseImpl,decltype(&DeleteBaseImpl)> m_ptrBase;        
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读