导读:本期聚焦于小伙伴创作的《C++怎么调用DLL函数?LoadLibrary与GetProcAddress动态库调用方法详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++怎么调用DLL函数?LoadLibrary与GetProcAddress动态库调用方法详解》有用,将其分享出去将是对创作者最好的鼓励。

在Windows平台的C++开发中,动态链接库(DLL)可以让程序在运行时按需加载功能模块,避免静态链接带来的体积膨胀问题。使用LoadLibrary配合GetProcAddress是动态调用DLL函数的标准方式,不需要在编译时链接.lib导入库,灵活性更高。

C++怎么调用DLL函数?LoadLibrary与GetProcAddress动态库调用方法详解

动态调用DLL的核心流程

整个调用过程可以分为四个核心步骤,每个步骤都有对应的Windows API函数支持,下面逐一说明。

1. 加载DLL文件

首先需要使用LoadLibrary函数加载目标DLL文件,该函数会返回DLL模块的句柄,后续操作都依赖这个句柄。函数原型如下:

// 加载指定路径的DLL,返回模块句柄,失败返回NULL
HMODULE LoadLibrary(
  LPCTSTR lpLibFileName  // DLL文件路径,可以是相对路径或绝对路径
);

如果DLL和exe文件在同一个目录,直接传入DLL文件名即可,否则需要传入完整路径。加载成功后需要判断是否返回有效句柄,避免后续操作出错。

2. 获取目标函数地址

拿到DLL模块句柄后,使用GetProcAddress函数获取DLL中导出函数的地址。函数原型如下:

// 根据函数名获取DLL中导出函数的地址,失败返回NULL
FARPROC GetProcAddress(
  HMODULE hModule,       // LoadLibrary返回的模块句柄
  LPCSTR  lpProcName     // 导出的函数名,注意是ANSI字符串
);

这里需要注意,传入的函数名必须是DLL实际导出的名称,如果DLL使用了C++的名称修饰,可能需要使用修饰后的名称,或者要求DLL用extern "C"导出函数避免名称修饰。

3. 定义函数指针并调用函数

获取到函数地址后,不能直接调用,需要先定义和DLL导出函数完全匹配的函数指针类型,再将地址转换为该指针类型后调用。函数指针的返回值、参数列表、调用约定都必须和DLL中的函数完全一致,否则会导致栈错误。

4. 释放DLL模块

调用完成后,需要使用FreeLibrary函数释放DLL模块,避免内存泄漏。函数原型如下:

// 释放已加载的DLL模块,返回非零值表示成功
BOOL FreeLibrary(
  HMODULE hLibModule  // LoadLibrary返回的模块句柄
);

完整示例代码

假设我们有一个名为demo.dll的动态库,其中导出了一个加法函数,函数原型为int add(int a, int b),且使用了extern "C"和__stdcall调用约定导出,下面是完整的调用代码:

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

// 定义和DLL导出函数匹配的函数指针类型
// 返回值int,两个int参数,调用约定__stdcall
typedef int (__stdcall *AddFunc)(int, int);

int main() {
    // 步骤1:加载DLL
    HMODULE hDll = LoadLibrary("demo.dll");
    if (hDll == NULL) {
        std::cout << "加载DLL失败,错误码:" << GetLastError() << std::endl;
        return -1;
    }

    // 步骤2:获取add函数地址
    AddFunc add = (AddFunc)GetProcAddress(hDll, "add");
    if (add == NULL) {
        std::cout << "获取函数地址失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hDll);
        return -1;
    }

    // 步骤3:调用函数
    int result = add(10, 20);
    std::cout << "调用add函数结果:" << result << std::endl;

    // 步骤4:释放DLL
    FreeLibrary(hDll);
    return 0;
}

注意事项与常见问题

  • 调用约定匹配:DLL导出函数的调用约定(__stdcall、__cdecl等)必须和函数指针定义的调用约定一致,否则会导致栈不平衡,程序崩溃。
  • 函数名称匹配:如果DLL是C++编写的且没有用extern "C"导出,函数名会被编译器修饰,需要使用工具(如Dependency Walker)查看实际导出的函数名,再传入GetProcAddress。
  • 错误排查:每次调用Windows API后,如果返回失败,可以通过GetLastError()获取错误码,对照Windows错误码表排查问题。
  • 32位与64位兼容:调用程序的位数必须和DLL的位数一致,32位程序不能加载64位DLL,反之亦然。
如果DLL提供了.lib导入库和头文件,也可以使用静态链接的方式调用,不需要手动使用LoadLibrary,但是动态调用的优势是可以在运行时决定是否加载DLL,更适合插件化架构的场景。

C++LoadLibraryGetProcAddressDLL调用动态库修改时间:2026-07-05 11:18:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。