Windows用dumpbin /exports、Linux用nm -D或objdump -T可查看动态库导出函数,但C++ name mangling导致符号名不可读;需extern "C"导出或undname解码,且须注意ABI兼容性与可见性设置。

Windows 下用 dumpbin /exports,Linux 下用 nm -D 或 objdump -T,就能直接看到动态库导出的函数名——但注意,C++ 编译器会对函数名做 name mangling(名字修饰),裸看输出基本看不懂。
Windows:用 dumpbin 看 DLL 导出函数,但得懂怎么“解码”修饰名
dumpbin /exports xxx.dll 输出里有三列:序号、偏移、符号名。关键在第三列:?func@NS@@YAXXZ 这种就是典型的 MSVC mangled name。它不是 C 风格的 func,不能直接拿去 GetProcAddress 用(除非你硬写这个修饰名)。
- 想让导出函数保持 C 风格命名,必须在 DLL 源码中用
extern "C"包裹声明,比如:extern "C" __declspec(dllexport) int my_add(int a, int b); - 如果已经只有 mangled 名,又想确认它对应哪个原型,可用
undname ?func@NS@@YAXXZ(MSVC 自带工具)反解 -
dumpbin不支持递归解析依赖库,只看当前 DLL;若需完整调用链,得配合depends.exe或Dependencies工具
Linux:nm -D 和 objdump -T 输出差异在哪?
nm -D libxxx.so 和 objdump -T libxxx.so 都能列出动态符号,但行为不同:
-
nm -D只显示 .dynamic 段里的符号(即真正可供 dlsym 查找的),更轻量,适合快速筛查 -
objdump -T输出更全,含符号值、大小、绑定类型(FUNC/OBJECT),还能加-C参数尝试 demangle(但对 GCC 5+ 的新 ABI 支持有限) - 如果看到符号是
U(undefined)而非T(text)或D(data),说明它不是本库导出的,而是外部依赖
C++ 函数导出后仍找不到?检查这三点
即使符号出现在 dumpbin 或 nm 列表里,GetProcAddress 或 dlsym 仍可能返回 nullptr:
立即学习“C++免费学习笔记(深入)”;
- Windows 下没加
extern "C"→ 传给GetProcAddress的必须是 mangled 名,不能传"my_func";或者改用GetModuleHandle+GetProcAddress配合undname确认真实符号 - Linux 下未用
__attribute__((visibility("default")))且编译时开了-fvisibility=hidden→ 即使函数定义了,也不会进动态符号表 - 调用方和库的 ABI 不匹配:比如库用 GCC 12 编译(默认启用
_GLIBCXX_USE_CXX11_ABI=1),而你的程序用旧版 GCC 链接,std::string类型的函数签名会因 ABI 差异彻底不兼容,nm能看见符号,dlsym却找不到
名字修饰和 ABI 兼容性是绕不开的坎,别只盯着工具输出的符号名是否“存在”,得确认它是否以你能调用的方式存在。

















