提问人:Sasan 提问时间:8/29/2021 最后编辑:Remy LebeauSasan 更新时间:8/29/2021 访问量:392
GetProcAddress 在 DLL 中找不到函数
GetProcAddress does not find function in DLL
问:
我有一个DLL,我想在其中调用一个函数。我使用 Dependency Walker 检查 DLL,得到的结果是:
void U2U_Test(void)
这是我编写的代码,但返回 NULL:GetProcAddress()
typedef void(*U2U_Test_pointer)();
void check() {
HINSTANCE hGetProcIDDLL1 = LoadLibrary(_T("my_dll.dll"));
if (hGetProcIDDLL1 == NULL)
return;
U2U_Test_pointer addr = (U2U_Test_pointer)GetProcAddress(hGetProcIDDLL1, "U2U_Test");
if (addr == NULL)
return;
return addr();
}
答:
0赞
QuentinC
8/29/2021
#1
根据使用的约定和编译器,在 DLL 中导出的实际名称可能与在源代码中编写的名称不完全相同。 这种现象通常称为名称装饰或名称篡改。
事实上,只有在以下情况下,您才能保证拥有完全相同的名称
- 你的编译器符合 C 约定(可能确实如此)
- 该函数以 C 而不是 C++ 导出。用于指定它。
extern "C"
- 调用约定_cdecl(在函数声明中指定)
__cdecl
例如,当调用约定__stdcall而不是 __cdecl时,这对于许多 Windows DLL 来说很常见(它们通常编写 WINAPI 或 CALLBACK 而不是 __sstdcall),导出函数的名称通常以 @n 为后缀,其中 n 是参数堆栈上预期的字节数。
就您而言,它可能是.
指示喜欢并告诉编译器在编译时导入/链接 DLL 时自动处理此类事情。U2U_Test@0
__declspec(dllimport)
__declspec(dllexport)
在 C++ 中,使用复杂的名称修饰来支持方法、函数重载、模板和其他功能,每个编译器都发明了疯狂的命名方案,以确保永远不会有任何冲突。
因为在 DLL 级别,没有模板,没有类,只有按其名称或 ID 索引的导出符号列表。
这就是为什么大多数 DLL 都是用 C 语言导出的,也是为什么大多数头文件在块内声明来自 DLL 的函数的原因。extern "C" { ... }
评论
GetProcAddress
不会说谎。加载的 DLL 中不存在名为该函数的函数。如果您说确实如此,请尽快联系 Microsoft,因为这是一个会影响数百万个程序的错误。U2U_Test
return addr();
void
addr();