【问题标题】:Delete instance of class from DLL从 DLL 中删除类的实例
【发布时间】:2020-02-20 08:51:59
【问题描述】:

我正在寻求帮助,以实现在 dll 库中正确释放内存。

我的项目结构如下:

库.dll:

  • interface.h -> 使用纯虚方法定义基类
  • implementation.h -> 从公共基类继承的派生类
  • implementation.cpp -> 派生类方法定义

implementation.h 还包含导出的函数:

extern "C" __declspec(dllexport) Base* __stdcall Create()
{
    return new Derived;
}

extern "C" __declspec(dllexport) void __stdcall Delete(Base* B)
{
    delete B;
}

Appllication.exe 代码如下所示:

#include "interface.h"
#include "windows.h"
#include <iostream>
#include <memory>

typedef Base* (*CREATE_BASE)();
std::unique_ptr<Base> SmartPointer;

int main()
{
    // Load the DLL
    HINSTANCE dll_handle = ::LoadLibrary(TEXT("Library.dll"));
    if (!dll_handle) {
        std::cout << "Unable to load DLL!\n";
        return 1;
    }

    // Get the function from the DLL
    CREATE_BASE Fn = (CREATE_BASE)GetProcAddress(dll_handle, "Create");
    if (!Fn) {
        std::cout << "Unable to load Create from DLL!\n";
        ::FreeLibrary(dll_handle);
        return 1;
    }

// i have possibility to use only C++11 so creation of unique_ptr looks like this:
SmartPointer = std::unique_ptr<Base>(Fn());

// ... do something like SmartPointer->Action();
::FreeLibrary(dll_handle);
return 0;
}

上面的代码有效,我可以轻松地初始化 Base 对象并执行 Derived 类中的函数。现在我想使用导出的“Delete”函数作为自定义指针删除器。于是我准备了类型的定义:

typedef void (*DELETE_BASE)(Base* B);

我想或多或少像这样使用它:

DELETE_BASE DeleteFn=(DELETE_BASE)GetProcAddress(dll_handle,"Delete");
SmartPointer = std::unique_ptr<Base>(Fn(),DeleteFn);

但是,我收到一个编译器错误,表明此 unique_ptr 定义不正确。如何解决这个问题?

我目前的解决方案是基于:

【问题讨论】:

    标签: c++ dll smart-pointers dllimport dllexport


    【解决方案1】:

    必须指定删除器函数的类型,因为您要覆盖默认删除器(请参阅std::unique_ptr<>)。

    您使用过的地方:

    std::unique_ptr<Base>
    

    您可能想使用:

    std::unique_ptr<Base, DELETE_BASE>
    

    【讨论】:

    • 按照你的建议,我进行了更改:std::unique_ptr SmartPointer;和 SmartPointer=std::unique_ptr(Fn(),DeleteFn);但我得到编译器错误:静态断言失败:'unique_ptr 用空删除器指针构造'
    • std::unique_ptr&lt;Base, DELETE_BASE&gt; 不能默认构造,因此将声明移至赋值,例如 std::unique_ptr&lt;Base, DELETE_BASE&gt; SmartPointer = std::unique_ptr&lt;Base, DELETE_BASE&gt;(Fn(), DeleteFn);
    • 感谢您的快速回复。看起来它可以工作,但这里出现了一个新问题 - 正如您可能猜到的那样,我支持 dll 文件中的函数的最终实现有点复杂。提到的 unique_ptr 应该是另一个类的成员,该类包含在初始化后使用它的函数。在这种情况下,当我同时声明和启动时,这是不可能的。有没有办法像类成员一样存储这个指针?
    • 虽然不是很优雅,我也没有尝试过,但我认为你可以将它包装在另一个 std::unique_ptr&lt;&gt; 中,例如 std::unique_ptr&lt;std::unique_ptr&lt;Base, DELETE_BASE&gt;&gt; myMember,这将允许默认构造 myMember,然后分配它你会使用类似instance.myMember = std::make_unique&lt;std::unique_ptr&lt;Base, DELETE_BASE&gt;&gt;(Fn(), DeleteFn));
    猜你喜欢
    • 1970-01-01
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    相关资源
    最近更新 更多