C++ 怎么调用DLL函数 C++ LoadLibrary与GetProcAddress【动态库】

发布时间 - 2026-01-30 00:00:00    点击率:
LoadLibrary失败先查GetLastError:126为依赖缺失,193为架构不匹配;用绝对路径、Dependency Walker查依赖、确保位数一致;C++导出需extern "C"防名字修饰;GetProcAddress返回值须强转为匹配调用约定的函数指针类型。

LoadLibrary 失败返回 NULL 怎么排查

调用 LoadLibrary 返回 NULL 是最常见卡点,不是路径错就是依赖缺失。先用 GetLastError() 拿错误码,再查对应含义——比如 126

表示找不到 DLL 或其某个依赖项(如 MSVCP140.dll),193 表示架构不匹配(x64 程序加载了 x86 DLL)。

实操建议:

  • 用绝对路径传给 LoadLibrary,避免当前工作目录干扰;路径中反斜杠必须双写:"C:\\path\\mylib.dll"
  • Dependency Walkerdumpbin /dependents mylib.dll 查看依赖项,确认所有 .dll 都在 PATH 或同目录
  • 确保进程位数与 DLL 一致:VS 中项目属性 → 配置管理器 → 平台必须匹配(Win32 ≠ x64)
  • 如果 DLL 有静态 C++ 运行时(/MT),而主程序用动态(/MD),可能引发初始化失败,此时 GetLastError 可能返回 1114(DLL 初始化例程失败)

GetProcAddress 找不到函数名?注意 C++ 名字修饰

直接传 "MyFunc"GetProcAddress 失败,大概率是 C++ 编译器对函数名做了修饰(name mangling)。DLL 导出的是 C 风格符号才可用原名查找;C++ 成员函数、重载函数、模板函数默认无法按名字导出。

实操建议:

  • DLL 工程中,用 extern "C" 包裹导出函数声明:
    extern "C" __declspec(dllexport) int MyFunc(int x);
  • 或者在 .def 文件里显式指定导出名,绕过修饰:
    EXPORTS
    MyFunc @1
  • dumpbin /exports mylib.dll 确认实际导出的符号名——如果看到类似 ?MyFunc@@YAHH@Z,说明没加 extern "C"
  • 不要试图用修饰后的名字硬写进代码,跨编译器不可靠;坚持用 extern "C" + 显式调用约定(如 __cdecl)最稳妥

函数指针类型声明不对会导致调用崩溃

GetProcAddress 返回 FARPROC(即 void*),必须强制转成**完全匹配的函数指针类型**,否则参数压栈、返回值解析全错,轻则结果异常,重则访问违规。

实操建议:

  • 定义 typedef 时,调用约定必须和 DLL 中一致:
    typedef int (__cdecl *MYFUNC)(int);
    MYFUNC pFunc = (MYFUNC)GetProcAddress(hMod, "MyFunc");
  • 忘记写 __cdecl 或写成 __stdcall 是高频崩溃原因;若 DLL 是 C 函数,默认是 __cdecl;若用 WINAPI(即 __stdcall)导出,这里也得同步
  • 参数个数、类型、顺序、返回值类型缺一不可;bool 和 BYTE、int 和 long 在不同平台可能宽度不同,尽量用 int32_t 等固定宽度类型
  • 调用前务必检查 pFunc != nullptr,否则直接崩溃

卸载 DLL 前必须确保没有线程正在执行其中代码

FreeLibrary 不会立即释放 DLL 内存,而是递减引用计数;但如果某线程正停在 DLL 函数里(比如等待 IO 或 sleep),此时调用 FreeLibrary,后续该线程恢复执行时就会访问已释放内存,导致未定义行为。

实操建议:

  • 除非明确需要热更新,否则通常不需要主动 FreeLibrary;进程退出时系统自动清理
  • 若必须卸载,确保所有调用方已退出相关函数,并且 DLL 内部无后台线程存活(比如它自己创建的 worker thread)
  • 可以配合 DisableThreadLibraryCalls(hMod) 减少线程附加/分离开销,但不影响安全性判断
  • 多次 LoadLibrary 同一个 DLL 会返回相同句柄,引用计数+1;对应要调用同样次数的 FreeLibrary 才真正释放
C++ 动态调用 DLL 的核心就三点:路径和依赖不出错、符号名不被修饰、函数指针类型严丝合缝。最容易忽略的是调用约定和跨模块类型对齐——看着能编译通过,跑起来崩得毫无征兆。


# cad  #   # c++  # win  # typedef  # lsp  # 架构  # NULL  # 成员函数  # extern  # bool  # int  # void  # 指针  # 重载函数  # 值类型  # 指针类型  # 线程  # Thread  # 的是  # 找不到  # 返回值  # 不匹配  # 严丝合缝  # 看着  # 都在  # 不需要  # 句柄  # 主程序 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 北京企业网站设计制作公司,北京铁路集团官方网站?  如何用IIS7快速搭建并优化网站站点?  Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  活动邀请函制作网站有哪些,活动邀请函文案?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Laravel定时任务怎么设置_Laravel Crontab调度器配置  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  如何在香港服务器上快速搭建免备案网站?  如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框  长沙企业网站制作哪家好,长沙水业集团官方网站?  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  浅谈javascript alert和confirm的美化  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  网站图片在线制作软件,怎么在图片上做链接?  b2c电商网站制作流程,b2c水平综合的电商平台?  Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践  phpredis提高消息队列的实时性方法(推荐)  Android自定义listview布局实现上拉加载下拉刷新功能  java ZXing生成二维码及条码实例分享  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  如何自定义建站之星网站的导航菜单样式?  Laravel安装步骤详细教程_Laravel环境搭建指南  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  Python自动化办公教程_ExcelWordPDF批量处理案例  香港服务器租用费用高吗?如何避免常见误区?  JS中对数组元素进行增删改移的方法总结  黑客如何利用漏洞与弱口令入侵网站服务器?  如何在云主机快速搭建网站站点?  Swift开发中switch语句值绑定模式  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  如何在橙子建站上传落地页?操作指南详解  高防服务器如何保障网站安全无虞?  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  Android使用GridView实现日历的简单功能  如何挑选高效建站主机与优质域名?  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  nodejs redis 发布订阅机制封装实现方法及实例代码  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  详解jQuery中的事件