【问题标题】:GetProcAddress does not find function in DLLGetProcAddress 在 DLL 中找不到函数
【发布时间】:2021-08-29 05:28:31
【问题描述】:

我有一个 DLL,我想在其中调用一个函数。我使用 Dependency Walker 检查 DLL,得到的结果是:

 void U2U_Test(void)

这是我写的代码,但是GetProcAddress()返回NULL:

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();
}

【问题讨论】:

  • 您会看到解构后的名称。导出的名称应该我弄错了。
  • GetProcAddress 不会说谎。您加载的 DLL 中不存在名为 U2U_Test 的函数。如果您说有,请尽快与 Microsoft 联系,因为这是一个会影响数百万个程序的错误。
  • 不相关,但return addr(); 在该功能中也没有任何意义。函数是void。那应该只是addr();
  • @S.M.你是对的,我应该使用 ?U2U_Test@@YAXXZ 作为函数名,它解决了问题。
  • @PaulMcKenzie 你是对的,GetProcAddress 不会说谎,但我正在寻找我的错误并在亲爱的 S.M. 的帮助下。我发现了我的错误。

标签: c++ getprocaddress dependency-walker


【解决方案1】:

根据使用的约定和编译器,DLL 中导出的实际名称可能与您在源代码中编写的名称不完全相同。 这种现象通常称为名称修饰或名称修饰。

事实上,只有在

  • 您的编译器符合 C 约定(可能确实如此)
  • 该函数以 C 而非 C++ 导出。使用extern "C" 指定它。
  • 调用约定是_cdecl(在函数声明中指定__cdecl

例如,当调用约定是 __stdcall 而不是 __cdecl,这在许多 Windows DLL 中很常见(他们经常写 WINAPI 或 CALLBACK 而不是 __sstdcall),导出函数的名称通常以 @n 为后缀,其中 n 是参数堆栈上预期的字节数。 在您的情况下,它可能是U2U_Test@0__declspec(dllimport)__declspec(dllexport) 等指示告诉编译器在编译时导入/链接 DLL 时自动处理这类事情。

在 C++ 中,为了支持方法、函数重载、模板和其他特性,使用了复杂的名称修饰,并且每个编译器都发明了疯狂的命名方案以确保不会发生任何冲突。 因为在 DLL 级别,没有模板,没有类,只有一个按名称或 ID 索引的导出符号列表。 这就是为什么大多数 DLL 都以 C 语言导出以及为什么大多数头文件在 extern "C" { ... } 块内声明来自 DLL 的函数的原因。

【讨论】:

    猜你喜欢
    • 2012-03-10
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多