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

时间:2015-07-29 06:32:52

标签: c++ c++11 dll raii

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

这就是我想要定义的内容:

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

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

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

更新

以下是新类的优缺点并使用std :: unique_ptr, 从答案中总结出来。

创建另一个 dll管理类

的优点:

  • 完全可控制以自定义DLL语义。
  • 将DLL相关部分隔离到一个有责任的类中。
  • 如果需要更多DLL功能,如曝光符号,则易于扩展。

缺点:

  • 需要重建RAII部分stadard自动指针已完成。
  • 有机会在RAII部分犯错。
  • 需要申报新班级。

A与自定义删除器一起使用

的优点:

  • 无需宣布另一个班级。
  • 重用std::unique_ptr的RAII部分。
  • 也许unique_ptr阻止复制DLL模块实例?

缺点:

  • Dll资源语义可能不适合标准自动指针,并且容易出错?
  • move semantics中的模板参数很复杂,很难找到错误的位置。
  • unique_ptrHMODULE,无类型,与unique_ptr集成可能有问题吗?

如果我错了,请在评论时纠正我。

4 个答案:

答案 0 :(得分:5)

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

Exception("HEYY!!")

答案 1 :(得分:5)

如果您使用::pointer来管理unique_ptr未提及的资源T,则需要为T*提供相应的T类型。此处unique_ptr::pointer的第一个模板参数。

如果未定义T*类型,则使用HMODULE*。在您的情况下,它的struct tLibraryDeleter { typedef HMODULE pointer; void operator()(HMODULE h) { FreeLibrary(h); } }; std::unique_ptr<HMODULE, tLibraryDeleter>(::LoadLibraryA("My.dll")); 是错误的。

--replace

结帐herehere

答案 2 :(得分:1)

  

看起来我仍然需要定义一个新类来管理DLL资源

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

为什么不这样?

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 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>的列表/数组似乎是一个糟糕的设计。

答案 3 :(得分:0)

请查看Windows Implementation Libraries (WIL)中的unique_hmodule

一个人可以按原样使用它,也可以只是借用它。