You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C++调用DLL问题:头文件仅提供函数指针typedef定义如何调用?

如何调用仅提供函数指针typedef的DLL函数

这事儿我太熟了,这种通过函数指针间接调用DLL函数的场景在老项目或者第三方闭源库中特别常见,我给你一步步说清楚操作流程,再附个完整示例:

核心步骤拆解

1. 加载目标DLL

首先你需要通过Windows API把DLL加载到当前进程的地址空间,用LoadLibrary或者它的宽字符版本LoadLibraryW都行。记得要检查加载是否成功,返回的HINSTANCE如果是NULL,说明加载失败(比如DLL路径不对、依赖缺失)。

2. 获取函数地址并转换为对应指针

GetProcAddress函数从加载的DLL中取出目标函数的地址,然后把它强制转换成头文件里给的typedef函数指针类型。这里要注意:

  • 第二个参数是文档里给的函数导出名(如果DLL用序号导出的话得用MAKEINTRESOURCE(序号),但你说文档给了函数名,直接传字符串就行)
  • 必须严格匹配typedef里的调用约定(比如你这里的__stdcall),不然会导致栈异常

3. 调用函数

转换完成后,你就可以像调用普通函数一样使用这个指针了。

4. 用完卸载DLL

调用FreeLibrary释放DLL资源,避免内存泄漏,尤其是在程序退出前或者不再需要DLL功能的时候。

完整代码示例

假设头文件里的typedef是:

typedef int (__stdcall *lpInitLib)();

那你的调用代码可以这么写:

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

// 假设这是头文件里的typedef
typedef int (__stdcall *lpInitLib)();

int main() {
    // 1. 加载DLL,这里替换成你的DLL实际路径
    HINSTANCE hDll = LoadLibraryA("YourTarget.dll");
    if (hDll == NULL) {
        std::cerr << "加载DLL失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    // 2. 获取函数地址并转换指针
    lpInitLib pInitLib = reinterpret_cast<lpInitLib>(GetProcAddress(hDll, "InitLib"));
    if (pInitLib == NULL) {
        std::cerr << "获取InitLib函数地址失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hDll); // 加载成功但获取函数失败,记得先卸载DLL
        return 1;
    }

    // 3. 调用函数
    int result = pInitLib();
    std::cout << "InitLib调用结果:" << result << std::endl;

    // 4. 卸载DLL
    FreeLibrary(hDll);

    return 0;
}

额外注意事项

  • 如果DLL里的函数有参数,只要typedef里的参数列表和文档一致,调用时直接传参就行,和普通函数完全一样
  • 调用约定一定要匹配!比如__stdcall__cdecl不能混,不然程序大概率崩溃
  • 如果你的程序是64位的,要确保DLL也是64位的;32位程序对应32位DLL,否则加载会失败

内容的提问来源于stack exchange,提问作者Jardo

火山引擎 最新活动