是否可以使用 std::unique_ptr 来管理 DLL 资源?

Is it possible to use std::unique_ptr to manage DLL resource?

我的项目中有很多LoadLibrary,需要为每个LoadLibrary手动调用FreeLibrary。我想将 std::unique_ptr 与特定的 deleter 一起使用,使其自动释放我的 dll 资源。

这就是我要定义的内容:

std::unique_ptr<HMODULE, BOOL(*)(HMODULE)> theDll(LoadLibrary("My.dll"), FreeLibrary);

但是编译器抱怨类型不匹配。我发现它期望从 LoadLibrary 得到 *HMODULE。也就是说 std::unique_ptr<A> 将期望 A* 作为其指针类型。看起来我仍然需要定义一个新的 class 来管理 DLL 资源(构造函数中的 LoadLibrary 和析构函数中的 FreeLibrary)。

是否可以让 std::unique_ptr<A> 只期望 A 作为它的指针类型?

已更新,

以下是新 class 和使用 std::unique_ptr 的优缺点, 从答案中总结。

再创建一个dll管理class,

优点:

缺点:

std::unique_ptr 与自定义删除器一起使用,

优点:

缺点:

如有错误请评论指正

It looks I still need to define a new class to manage DLL resource

为什么你认为这是个坏主意?

为什么不这样?

class DynamicLibrary
{
protected:
    HANDLE      _handle;
    string      _path;

public:
    DynamicLibrary();
    DynamicLibrary(const string& path, bool autoLoad = false); // if(autoLoad) this->Load()

    ~DynamicLibrary(); // if(this->IsLoaded()) this->Unload()

    Result Load(); // LoadLibrary() here
    void Unload(); //FreeLibrary() here

    bool IsLoaded() const; // return this->_handle != nullptr
};

然后,您甚至可以扩展此 class 以使符号检索更清晰:

class DynamicLibrary
{
    //cut

    void* RetrieveSymbol(const char* symName) const;

    template <class Cast_type>
    Cast_type RetrieveSymbolAs(const char* symName) const;
};

示例:

DynamicLibrary lib("XXX.dll", true);
assert( lib.IsLoaded() );

FuncType dll_func = lib.RetrieveSymbolAs<FuncType>("dll_func_name");

我认为,旨在表示 DLL 实例的显式类型要好得多。然后,您可以存储此类对象的数组,所有这些都会自动进行。干净、简单、易于实施。

存储 std::unique_ptr<HANDLE, Some_custom_unloader> 的 list/array 在我看来是个糟糕的设计。

根据this page,HMODULE是HINSTANCE,HINSTANCE是HANDLE,HANDLE是PVOID,PVOID是void *。这意味着 HMODULE 是指针类型。所以以下应该有效:

std::unique_ptr<std::remove_pointer_t<HMODULE>, BOOL(*)(HMODULE)> theDll(LoadLibrary("My.dll"), FreeLibrary);

如果您使用它来管理 T* 未引用的资源 T,则需要为 unique_ptr 提供相应的 ::pointer 类型。这里 Tunique_ptr.

的第一个模板参数

如果没有::pointer类型未定义,则使用T*。在您的情况下,HMODULE* 是错误的。

struct tLibraryDeleter
{
  typedef HMODULE pointer;
  void operator()(HMODULE h) { FreeLibrary(h); }
};

std::unique_ptr<HMODULE, tLibraryDeleter>(::LoadLibraryA("My.dll"));

查看 here and here

请在Windows Implementation Libraries (WIL)

中查看unique_hmodule

可以按原样使用它,也可以借用它的实现。