我有一个静态库,可以链接到.exe
或.dll
。在运行时,我希望我的库函数可以获得HMODULE
以获取静态库代码链接到的任何内容。
我目前使用以下技巧(灵感来自this forum):
const HMODULE GetCurrentModule()
{
MEMORY_BASIC_INFORMATION mbi = {0};
::VirtualQuery( GetCurrentModule, &mbi, sizeof(mbi) );
return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}
有没有更好的方法来做这个看起来不那么hacky?
(注意:这样做的目的是加载一些我知道我的用户将与我的静态库同时链接的Win32资源。)
答案 0 :(得分:49)
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModule,
&hModule);
return hModule;
}
答案 1 :(得分:29)
__ImageBase
是链接器生成的符号,它是模块的DOS头(仅限MSVC)。您可以将其地址转换为HINSTANCE
或HMODULE
。所以它比通过API更方便。
所以你只需要这样做:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
来自http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
答案 2 :(得分:3)
我会使用标记GetModuleHandleEx()
查看GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
。看起来您可以更改GetCurrentModule()
来调用此例程而不是VirtualQuery()
,并将GetCurrentModule()
的地址作为lpModuleName
参数传递。
ETA:
const HMODULE GetCurrentModule()
{
DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
HMODULE hm = 0;
::GetModuleHandleEx( flags, reinterpret_cast<LPCTSTR>( GetCurrentModule ), &hm );
return hm;
}
我没有尝试过,但我认为你会做你想做的事。
答案 3 :(得分:0)
#if _MSC_VER >= 1300 // for VC 7.0
#ifndef _delayimp_h
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif
#endif
...
HMODULE module()
{
#if _MSC_VER < 1300 // earlier than .NET compiler (VC 6.0)
MEMORY_BASIC_INFORMATION mbi;
static int address;
;::VirtualQuery(&address, &mbi, sizeof(mbi));
return reinterpret_cast(mbi.AllocationBase);
#else // VC 7.0
// from ATL 7.0 sources
return reinterpret_cast(&__ImageBase);
#endif
}
更多https://www.apriorit.com/dev-blog/74-hmodule-hinstance-handle-from-static-library-in-c
答案 4 :(得分:-4)
HMODULE是HINSTANCE是模块的基地址。所以,我会看到它是如何工作的。但是,如果你想要的只是可执行文件的HMODULE,为什么不在进程中枚举所有HMODULE(EnumProcessModules)。其中一个将链接你的.lib。
我看到的限制是您不知道.lib来自哪个DLL或EXE。您可能希望将HMODULE(基址)与从.lib获得的_ReturnAddress进行比较。您的.lib将属于小于_ReturnAddress
的最高HMODLUE