getprocaddress 返回 null 的最常见原因是函数名不匹配(如 c++ 名称修饰导致导出名非裸名),而非函数未导出;需用 dumpbin /exports 查看真实导出名,配合 extern "c" 和一致调用约定,并确保 dll 已由 loadlibrary 正确加载。

直接说结论:用 GetProcAddress 加载 DLL 中的导出函数,必须确保函数名完全匹配(含修饰)、调用约定一致、且 DLL 已被正确加载;否则返回 NULL,不是“找不到函数”,而是“符号解析失败”。
为什么 GetProcAddress 总是返回 NULL?
最常见原因不是函数没导出,而是名字对不上。C++ 编译器会对函数名做名称修饰(name mangling),比如 int add(int, int) 在 MSVC 下可能变成 ?add@@YAHHH@Z。此时传入 "add" 肯定查不到。
- 用
dumpbin /exports your.dll(Windows SDK 工具)查看真实导出名,确认是 C 风格(无修饰)还是 C++ 风格(带修饰) - 如果希望保持简单名字,导出函数必须用
extern "C"声明,且推荐加上__declspec(dllexport) - 在 DLL 源码中写:
extern "C" __declspec(dllexport) int my_calc(int a, int b) { return a + b; } - 这样导出名就是裸的
"my_calc",GetProcAddress(hMod, "my_calc")才能成功
GetProcAddress 返回的函数指针怎么安全调用?
它只返回 FARPROC(即 void *),不带类型信息。强制调用前必须显式转成正确的函数指针类型,否则参数压栈/返回值处理错位,轻则结果错误,重则崩溃。
- 定义匹配的函数类型别名,例如:
typedef int (*calc_func_t)(int, int);
- 获取并转换:
calc_func_t pfn = (calc_func_t)GetProcAddress(hMod, "my_calc");
- 务必检查
pfn != NULL再调用,不要跳过这步 - 注意调用约定:若 DLL 中是
__stdcall(如 Windows API 风格),类型定义里也得写int (__stdcall *func_t)(...),否则栈清理错乱
加载 DLL 时 LoadLibrary 失败的几个隐蔽点
LoadLibrary 失败会导致后续所有 GetProcAddress 无效,但它失败的原因往往不直观。
- 路径问题:传入相对路径时,Windows 按特定顺序搜索(当前目录、系统目录、PATH 等),建议用绝对路径或
SetDllDirectory显式控制 - 依赖缺失:目标 DLL 依赖的其他 DLL(如
MSVCP140.dll)不在路径中,LoadLibrary会静默失败 —— 用Dependency Walker或Dependencies.exe查看实际依赖树 - 位数不匹配:32 位程序不能加载 64 位 DLL,反之亦然;编译目标平台必须和 DLL 一致
- 权限或文件占用:DLL 正被其他进程锁定,或当前用户无读取权限(少见但存在)
真正麻烦的不是语法,而是名字修饰、调用约定、依赖链这三层嵌套问题。哪怕 GetProcAddress 一行代码写对了,前面任意一环出错,结果都是 NULL —— 而它从不告诉你为什么。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











