从控制台应用程序动态使用 DLL

Dynamically use a DLL from a console application

我正在尝试创建一个库 Lib.dll 以从控制台应用程序动态调用,但找不到我要调用的函数 funci()

Lib.dll 是 Visual Studio 2019 年创建的项目(控制台应用程序,但设置为配置类型:.dll)的成果。

Lib.cpp 是该项目中唯一的文件,并且只包含代码:

__declspec(dllexport) int funci() 
{
    return 50;
}

我认为我正在正确导出函数,因为我使用 DLL Export Viewer v1.66 找到了函数。

但是,我很难通过我的控制台应用程序 (.exe) 找到该功能:

#include <windows.h>
#include <iostream>

typedef int(__cdecl* o_funci)(void);

o_funci funci;

int main()
{
    HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\Lib.dll");

    if (!hGetProcIDDLL) {
        std::cout << "could not load the dynamic library" << std::endl;
        return EXIT_FAILURE;
    }

    // resolve function address here
    funci = (o_funci) GetProcAddress(hGetProcIDDLL, "funci");
    if (!funci) {
        std::cout << "could not locate the function" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "funci() returned " << funci() << std::endl;

    FreeLibrary(hGetProcIDDLL);
}

GetProcAddress 出现问题,但不知道原因。我哪里错了?

输出:

我一直在看这个旧的post:Dynamically load a function from a DLL


编辑:感谢 tenfour

解决了

我使用了 DependencyWalker。

没有 extern "C" 我可以看到未修饰的 funci 的名字是 ?funci@@YGHXZ,

所以 funci = (o_funci)GetProcAddress(hGetProcIDDLL, "?funci@@YGHXZ"); 成功了。

extern "C" 一起,未修饰的 funci 的名称为 _funci@0 - 更干净一些。

另一个注意事项;使用序数 0x0001 在这两种情况下都有效。像这样:funci = (o_funci)GetProcAddress(hGetProcIDDLL, (PCSTR)0x0001);

您使用的工具显示的是导出名称的漂亮版本。它的真实名称将包含名称修改,这是一种将调用信息嵌入到导出名称中的复杂尝试。

您有多种选择可以使这项工作与 GetProcAddress:

  1. 使用真实的导出名称。您的工具可能可以选择查看未美化的名称(损坏的导出名称)
  2. 使用模块定义文件 (*.def) 导出函数,您甚至可以在其中指定导出的名称
  3. 按序号而不是名称导入
  4. 将函数包装在 extern "C" { ... } 中,这将使用 C 风格命名,从而避免名称混淆。

最常见的解决方案可能是#4,紧随其后的是#2。