Windows下C++导出DLL函数必须加__declspec(dllexport),否则调用方报“找不到符号”;推荐用extern "C"导出纯C接口,避免ABI不兼容、内存管理混乱及CRT混用问题。

导出函数时忘记加 __declspec(dllexport),调用方会报“找不到符号”
Windows 下 C++ 编译 DLL 时,函数默认不对外可见。哪怕你写了实现、头文件也声明了,没加导出标记,链接器根本不会把符号放进 DLL 的导出表里。LoadLibrary 能成功,但 GetProcAddress 一定返回 NULL,或者隐式链接时报 LNK2019: unresolved external symbol。
- 显式导出:在函数定义前加
__declspec(dllexport),比如extern "C" __declspec(dllexport) int add(int a, int b); - 隐式导出更常用:用模块定义文件(
.def),里面写EXPORTS段,避免 C++ 名字修饰问题;但必须确保.def文件被正确加入项目构建流程(VS 里要设为“模块定义文件”属性) - 别用
inline函数导出——它通常不生成独立符号,导出无效 - 如果头文件同时供 DLL 和 EXE 使用,用宏区分:
#ifdef BUILDING_MYDLL控制__declspec(dllexport)/__declspec(dllimport)
C++ 类导出比函数麻烦得多,多数情况该换思路
直接导出整个类(尤其是含虚函数、模板、STL 成员的类)极易因 ABI 不兼容崩溃。不同编译器、不同运行时版本、甚至同一编译器不同优化选项,都可能让 vtable 布局或内存布局不一致。
- 安全做法是只导出纯 C 风格接口:用
extern "C"导出工厂函数(如create_processor())和操作函数(如process_data(ctx, buf, len)),内部用指针隐藏实现 - 若真要导出类,必须确保 DLL 和调用方用完全相同的编译器、标准库、运行时(/MD 或 /MT 一致)、甚至相同版本的 STL 头文件
- 导出类时,构造/析构函数必须显式导出,且不能依赖静态局部变量初始化顺序——DLL 加载时机不确定
- 别导出模板类本身,可以导出其实例化后的具体类型(如
MyContainer<int></int>),但依然受限于 ABI
隐式链接 vs 显式链接:选错会导致程序启动失败或热更新失效
隐式链接(#pragma comment(lib, "mydll.lib") + 头文件声明)简单,但要求 DLL 在 PATH 或可执行目录下,且启动时必须存在;显式链接(LoadLibrary + GetProcAddress)灵活,能延迟加载、容错、热替换,但代码稍多。
- 隐式链接失败直接弹窗报错(“找不到 mydll.dll”),无法捕获处理;显式链接返回
NULL,你可以提示用户、降级功能或尝试备用路径 - 显式链接要注意函数指针类型必须严格匹配,建议用
typedef定义,比如typedef int (*add_func)(int, int);,再强制转换,否则调用时栈错乱 - 隐式链接的导入库(
.lib)不是静态库,只是桩,真正符号来自 DLL;别误删 DLL 只留.lib - 调试时注意:VS 默认不把 DLL 复制到输出目录,手动加“生成事件”或项目依赖,否则 F5 启动就失败
字符编码和运行时混用:DLL 里用 std::string 传参大概率出问题
Windows 上常见坑是 DLL 和主程序用了不同 CRT(C 运行时),比如一个用 /MDd(调试版多线程 DLL),另一个用 /MT(静态链接),这时 std::string 的内存分配器不互通,new/delete 跨 DLL 调用会崩。
立即学习“C++免费学习笔记(深入)”;
- 跨 DLL 边界禁止传递 STL 容器、智能指针、异常对象;统一用裸指针 + 长度参数,比如
void process(const char* data, size_t len) - 字符串优先用宽字符
wchar_t*+UTF-16,避免std::string编码歧义;或约定 UTF-8 编码 +const char* - 所有内存分配/释放必须发生在同一侧:DLL 分配的内存,必须由 DLL 提供
free_buffer()接口释放 - 别在 DLL 入口(
DllMain)里调用LoadLibrary、CreateThread或任何可能触发 CRT 初始化的函数——死锁高发区
C++ 写 DLL 最难的从来不是语法,而是 ABI 稳定性和内存生命周期的边界控制。很多崩溃不是代码写错了,而是两边对“谁负责分配、谁负责释放、用哪个堆、按什么规则解构”没达成无声共识。










