我的项目中有很多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管理类,
的优点:
缺点:
将A
与自定义删除器一起使用
的优点:
std::unique_ptr
的RAII部分。unique_ptr
阻止复制DLL模块实例?缺点:
move semantics
中的模板参数很复杂,很难找到错误的位置。unique_ptr
是HMODULE
,无类型,与unique_ptr集成可能有问题吗?如果我错了,请在评论时纠正我。
答案 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
答案 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
一个人可以按原样使用它,也可以只是借用它。