【问题标题】:GetProcAddress() failing, error 127GetProcAddress() 失败,错误 127
【发布时间】:2014-11-10 17:14:54
【问题描述】:

这是我的 DLL 代码:

#include <Windows.h>
#include <iostream>

int sysLol(char *arg);

int sysLol(char *arg)
{
   std::cout<<arg<<"\n";
   return 1;
}

这是我的应用程序代码:

#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <stdlib.h>

typedef int (WINAPI* Lol)(char* argv);
struct PARAMETERS
{
    DWORD Lol;
};

int main()
{
    PARAMETERS testData;
    HMODULE e = LoadLibrary(L"LIB.dll"); //This executes without problem
    if (!e) std::cout<<"LOADLIBRARY: "<<GetLastError()<<"\n";
    else std::cout<<"LOADLIBRARY: "<<e<<"\n";
    testData.Lol = (DWORD)GetProcAddress(e,"sysLol"); //Error 127?
    if (!testData.Lol) std::cout<<testData.Lol<<" "<<GetLastError()<<"\n";
    else std::cout<<"MESSAGEBOX: "<<testData.Lol<<"\n";
    std::cin.ignore();
    return 1;
}

所以,我的 LIB.dll 使用 LoadLibrary() 成功加载,但 GetProcAddress() 失败并显示 127。 这似乎是因为它没有找到我的函数名称,但我不明白为什么会失败。

非常感谢您的帮助! :) ~P

【问题讨论】:

    标签: c++ dll loadlibrary getprocaddress


    【解决方案1】:

    由于该标记是 C++,因此您需要为函数声明一个 C 名称:

    extern "C" int sysLol(char *arg);
    

    您可以使用Dependency Walker 查看编译器为您的 C++ 函数提供的实际名称。

    成功后,将函数转换为 GetProcAddress 返回的指针到实际的函数类型:

    typedef int (*sysLol_t)(char *arg);
    sysLol_t pFunc = GetProcAddress(e,"sysLol");
    

    【讨论】:

      【解决方案2】:

      ERROR_PROC_NOT_FOUND,这意味着没有具有该名称的导出函数。

      没什么好说的了。也许你把名字弄错了。这可能是字母大小写的简单不匹配。可能 DLL 构建不正确并且没有导出函数。也许 DLL 正在修饰或修改名称。当然,从问题中的代码来看,没有证据表明您试图导出该函数,或者确实抑制了装饰/修改。

      使用 dumpbin 或 Dependency Walker 之类的工具来检查导出的函数的名称。这可能会对问题有所启发。

      LoadLibraryGetProcAddress 在运行时链接相比,在加载时链接要方便得多。使用构建 DLL 时生成的 .lib 导入库来执行此操作。

      还值得指出的是调用约定不匹配。您在 DLL 端有 cdecl,在可执行端有 stdcall。并且不要将指针指向DWORD。当你编译为 64 位时,结果很糟糕。

      【讨论】:

      • 嗯,这旨在与进程注入一起使用,因此加载时链接对我来说不是一个选项。调用约定不匹配,因为实际来源比我发布的要复杂得多,所以我不得不通过并快速将代码压缩成您在上面看到的内容。很可能我犯了一个快速打字错误。至于转换为 DWORD,现在我的进程注入指向 32 位进程,并且正在编译为 32 位可执行文件,但我确实计划最终将其扩展为 64 位,所以感谢您的提示。 :)
      • 没关系。我从我能看到的情况中回答。我仍然认为我回答了你的问题。
      • 把你的函数放在一个外部“C”块中。使用 __declspec(dllexport) 和 cdecl 没有重整。如果您需要不同的调用约定,请使用 def 文件导出。
      • @TamásSzelei 否。结果为ERROR_MOD_NOT_FOUND
      • @tamás 也许我们可以整理这些 cmets
      【解决方案3】:

      符号必须从 Windows DLL 中显式导出。将您的函数声明为__declspec(dllexport) 或将 DEF 文件传递​​给链接器以指示它导出您的函数。见this description of dllexport.

      【讨论】:

      • 这似乎是一个开始,但显然我的函数名被装饰了。我现在正在谷歌上搜索,但是当我在这里时,您知道在 Visual Studio 2012 环境中解决此问题的任何方法吗?
      【解决方案4】:

      请使用 Dependancy Walker,它会提示注册在 dll 中的方法名称。

      http://www.dependencywalker.com/

      如果方法名是- getNumber Dependency Walker 将显示实际方法名称为-_Z9GetNumberd

      前-

      lpGetNumber = (LPGETNUMBER)GetProcAddress(hDLL, "_Z9GetNumberd");
      

      现在LoadLibraryGetProcAddress() 都可以工作了。

      【讨论】:

      • edit您的答案以改进格式并删除所有大写字母。
      • Augen,请澄清为什么这个答案没有用,为什么你对我投了反对票?
      • 我对此投了反对票,因为糟糕的格式使它很难阅读,因此几乎没用。我看现在已经修好了。尽管实际有用性仍有待商榷,因为答案与公认的答案几乎相同,没有extern "C" 替代方案。无论如何,现在删除反对票。
      【解决方案5】:

      使用 DependencyWalker,您可以查看已修饰/未修饰的函数(查看->未修饰 C++ 函数)

      尝试使用修饰函数名形式调用 GetProcAddress。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-03
        • 1970-01-01
        • 1970-01-01
        • 2016-01-28
        • 2016-04-13
        • 1970-01-01
        • 2018-09-10
        相关资源
        最近更新 更多