C++怎么写动态库 C++生成DLL与调用DLL详细步骤【工程】

发布时间 - 2026-02-02 00:00:00    点击率:
正确配置生成DLL需确保三点:项目属性设为Dynamic Library;源文件用__declspec(dllexport)或.def文件导出符号;头文件用宏区分dllimport/dllexport并加extern "C"防名字修饰。

Visual Studio 项目中怎么正确配置生成 DLL

生成 DLL 的关键不是写代码,而是让编译器知道“这个工程要导出符号”。默认新建的 C++ 动态库项目(DLL)已设好基础配置,但手动建空项目或从静态库改过来时极易漏掉 __declspec(dllexport) 或项目属性设置。

必须确认以下三点:

  • 项目属性 → 配置属性 → 常规 → “配置类型”为 Dynamic Library (.dll)
  • C++ 源文件中,所有要被外部调用的函数/类,必须显式标记导出:用 __declspec(dllexport)(Windows 特有),或更推荐的方式——通过模块定义文件(.def)统一导出
  • 若使用 __declspec(dllexport),建议配合宏封装,避免在调用方误用:例如定义 #define MYDLL_API __declspec(dllexport),并在头文件中对导出函数加该宏;调用方则用 __declspec(dllimport)

不加导出声明的函数,即使编译成 DLL,链接时也会报 LNK2019: unresolved external symbol

头文件里如何安全声明 DLL 导出函数

头文件是调用方和实现方的契约。写错会导致编译通过但运行崩溃,或链接失败。

典型错误是直接在头文件里写 __declspec(dllexport) —— 这会让调用方也尝试导出,引发重复定义或链接错误。

正确做法是用宏区分编译角色:

#ifdef BUILDING_

MYDLL #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif

extern "C" { MYDLL_API int add(int a, int b); }

其中 BUILDING_MYDLL 是你在 DLL 工程的“预处理器定义”里手动添加的宏(项目属性 → C/C++ → 预处理器 → 预处理器定义)。这样头文件在 DLL 编译时展开为 dllexport,在调用方编译时展开为 dllimport

extern "C" 是为了禁用 C++ 名字修饰(name mangling),否则 C++ 函数导出后名字乱码,C# 或其他语言根本没法调用。

隐式链接调用 DLL 的完整步骤(.lib + .h + .dll 缺一不可)

这是最常用、最稳妥的调用方式,但三者路径和内容必须严格匹配,否则运行时报 0xc000007b找不到指定模块

调用方工程需配置:

  • 包含目录:指向 DLL 工程的头文件所在路径(如 $(SolutionDir)MyDll\include
  • 库目录:指向生成的 .lib 文件所在目录(如 $(OutDir),即 DLL 输出目录)
  • 附加依赖项:填入 MyDll.lib(注意不是 MyDll.dll
  • 运行时把 MyDll.dll 放到调用方可执行文件同目录下(或系统 PATH 路径中)

常见坑:

  • 用了 x64 DLL,但调用方是 Win32 配置 → 直接加载失败,错误码 ERROR_BAD_EXE_FORMAT
  • 忘记复制 .dll 到输出目录,调试时提示 LoadLibrary failed: 126
  • 头文件里声明了函数,但 DLL 工程没实际实现,或导出名不一致(尤其没加 extern "C" 时)→ 运行时 GetProcAddress 返回 NULL

用 LoadLibrary + GetProcAddress 手动加载 DLL(适用于插件场景)

这种方式绕过链接期绑定,适合运行时决定是否加载、或多版本共存等场景,但写法稍繁琐,且失去编译期类型检查。

核心是三步:

  • LoadLibrary(L"MyDll.dll") 获取模块句柄(返回 HMODULE
  • GetProcAddress(hModule, "add") 获取函数地址(注意:C++ 函数名需用修饰后名字,除非加了 extern "C";C 函数名就是字符串字面量)
  • 把返回值强制转为函数指针类型再调用,例如:typedef int (*ADD_FUNC)(int, int); ADD_FUNC pAdd = (ADD_FUNC)GetProcAddress(...); int r = pAdd(3, 4);

必须检查每一步返回值:如果 LoadLibrary 返回 NULL,用 GetLastError() 查具体原因(比如路径错、依赖缺失、位数不匹配);如果 GetProcAddress 返回 NULL,大概率是函数名拼错或未导出。

别忘了最后调用 FreeLibrary(hModule),否则 DLL 句柄泄漏,多次加载后进程无法退出。

导出类比导出函数更复杂,涉及虚表、内存分配器一致性等问题,除非明确需要跨 DLL 边界传递对象,否则优先用纯 C 风格函数接口。另外,DLL 中尽量避免使用 STL 容器作为参数或返回值——不同模块可能用不同版本 CRT,导致析构崩溃。


# windows  # 处理器  # cad  # ai  # c++  # win  # c#  # typedef  # lsp  # NULL  # define  # 封装  # include  # extern  # 字符串  # 预处理器  # int  # 指针  # 接口  # 指针类型  # symbol  # 对象  # visual studio  # 头文件  # 加载  # 句柄  # 返回值  # 三点  # 会报  # 这是  # 找不到  # 你在  # 设为 


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


相关推荐: 如何在Ubuntu系统下快速搭建WordPress个人网站?  如何在VPS电脑上快速搭建网站?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  Laravel怎么多语言本地化设置_Laravel语言包翻译与Locale动态切换【手册】  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  android nfc常用标签读取总结  Laravel如何实现事件和监听器?(Event & Listener实战)  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Laravel如何处理和验证JSON类型的数据库字段  零基础网站服务器架设实战:轻量应用与域名解析配置指南  Laravel如何使用查询构建器?(Query Builder高级用法)  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  ,怎么在广州志愿者网站注册?  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  如何自定义建站之星网站的导航菜单样式?  Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何在IIS7上新建站点并设置安全权限?  Laravel如何实现API资源集合?(Resource Collection教程)  nodejs redis 发布订阅机制封装实现方法及实例代码  如何快速重置建站主机并恢复默认配置?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  Laravel怎么连接多个数据库_Laravel多数据库连接配置  Laravel如何优化应用性能?(缓存和优化命令)  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  个人网站制作流程图片大全,个人网站如何注销?  再谈Python中的字符串与字符编码(推荐)  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  Python自动化办公教程_ExcelWordPDF批量处理案例  韩国服务器如何优化跨境访问实现高效连接?  php打包exe后无法访问网络共享_共享权限设置方法【教程】  郑州企业网站制作公司,郑州招聘网站有哪些?  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  如何用VPS主机快速搭建个人网站?  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  如何在阿里云通过域名搭建网站?  LinuxShell函数封装方法_脚本复用设计思路【教程】  音乐网站服务器如何优化API响应速度?  无锡营销型网站制作公司,无锡网选车牌流程?  黑客如何利用漏洞与弱口令入侵网站服务器?  在线制作视频的网站有哪些,电脑如何制作视频短片?  Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试  Laravel如何实现一对一模型关联?(Eloquent示例)  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  如何在服务器上配置二级域名建站?  如何获取上海专业网站定制建站电话?  如何快速搭建高效简练网站?