当前位置: 首页 > backend >正文

【C++】显示与隐式加载dll的使用与区别

一、什么是 DLL?

DLL(Dynamic Link Library) 是 Windows 下的动态链接库,包含可被多个程序共享的函数、资源或类。使用 DLL 可以实现代码复用、模块化设计和插件机制。

在 C++ 中,调用 DLL 中的函数有两种主要方式:

  1. 隐式链接(Implicit Linking)
  2. 显式链接(Explicit Linking)

二、隐式链接(Implicit Linking)

1. 原理

程序启动时自动加载 DLL,通过 .lib 导入库将 DLL 中的函数符号链接到可执行文件中。

2. 使用步骤

(1)准备三个文件:

  • MyDll.dll:动态库文件
  • MyDll.lib:导入库(由 DLL 生成)
  • MyDll.h:声明导出函数

(2)头文件示例(MyDll.h)

#ifdef __cplusplus
extern "C" {
#endif__declspec(dllimport) int Add(int a, int b);#ifdef __cplusplus
}
#endif

注意:dllimport 表示从 DLL 导入函数。

(3)链接 .lib 文件

在项目中添加 .lib 路径,并链接:

#pragma comment(lib, "MyDll.lib")

(4)直接调用函数

#include "MyDll.h"int result = Add(3, 4); // 直接像普通函数一样调用

3. 特点

优点缺点
使用简单,像调用本地函数启动时必须找到 DLL,否则程序无法启动
编译期检查函数签名不支持动态选择或延迟加载
性能略高(无需查表)难以实现插件系统或热更新

三、显式链接(Explicit Linking)

1. 原理

运行时通过 LoadLibraryGetProcAddress 手动加载 DLL 并获取函数地址。

2. 使用步骤

(1)不需要 .lib 文件,只需:

  • MyDll.dll
  • MyDll.h(知道函数原型)

(2)加载 DLL 并获取函数指针

#include <windows.h>
#include <iostream>// 定义函数指针类型
typedef int (*AddFunc)(int, int);int main()
{HMODULE hDll = LoadLibrary(_T("MyDll.dll")); // 加载 DLLif (hDll == NULL) {std::cout << "无法加载 DLL!" << std::endl;return -1;}// 获取函数地址AddFunc Add = (AddFunc)GetProcAddress(hDll, "Add");if (!Add) {std::cout << "无法找到函数 Add!" << std::endl;FreeLibrary(hDll);return -1;}// 调用函数int result = Add(3, 4);std::cout << "结果:" << result << std::endl;// 卸载 DLLFreeLibrary(hDll);return 0;
}

3. 特点

优点缺点
运行时动态加载,灵活使用复杂,需手动管理函数指针
可判断 DLL 是否存在,提供降级方案无编译期检查,易出错(函数名拼错)
支持插件系统、热更新、按需加载性能稍低(需查表)
程序可容忍缺失 DLL需要正确处理 FreeLibrary 防止内存泄漏

 

四、核心区别对比表

对比项隐式链接显式链接
加载时机程序启动时自动加载运行时手动加载(LoadLibrary
是否需要 .lib否(可选)
函数调用方式直接调用(如 Add(1,2)通过函数指针调用
启动依赖必须存在 DLL,否则无法启动可容忍缺失,运行时报错
灵活性高(可动态选择、卸载、替换)
适用场景核心功能、稳定依赖插件、可选模块、第三方组件
错误处理启动失败可在运行时提示用户
性能略高略低(需查找符号)
典型 API无(编译器自动处理)LoadLibraryGetProcAddressFreeLibrary

五、如何选择?

场景推荐方式
程序核心功能依赖的 DLL(如运行库)✅ 隐式链接
第三方 SDK、硬件驱动接口✅ 显式链接(容错更好)
实现插件系统(如 Photoshop 滤镜)✅ 显式链接
需要热更新或动态替换模块✅ 显式链接
小项目、简单调用、DLL 一定存在✅ 隐式链接更方便

六、最佳实践建议

  • 优先考虑显式链接 用于第三方或可选模块,提升程序健壮性。
  • 使用 RAII 封装 HMODULE,避免忘记 FreeLibrary
class DllLoader {
public:DllLoader(const TCHAR* name) { hDll = LoadLibrary(name); }~DllLoader() { if (hDll) FreeLibrary(hDll); }HMODULE get() { return hDll; }
private:HMODULE hDll = nullptr;
};
  • 导出 C 函数(用 extern "C")避免 C++ 名称修饰问题。
  • 在发布程序时,确保 DLL 路径正确(当前目录、系统路径、应用程序目录等)。

七、补充:如何导出 DLL 函数?

// MyDll.cpp
extern "C" __declspec(dllexport) int Add(int a, int b)
{return a + b;
}

extern "C" 防止 C++ 编译器名称修饰,便于 GetProcAddress 查找。

总结

方式何时用关键词
隐式链接简单、固定依赖.lib、启动加载、直接调用
显式链接灵活、容错、插件LoadLibraryGetProcAddress、运行时加载

💬 一句话总结:

  • 简单直接 → 用 隐式链接
  • 灵活可控 → 用 显式链接

 

显示声明与隐式声明的使用与区别

【C++】显示声明与隐式声明的使用与区别-CSDN博客文章浏览阅读1.1k次,点赞17次,收藏19次。【C++】显示声明与隐式声明的使用与区别_隐式声明 https://blog.csdn.net/wangnaisheng/article/details/142489678?spm=1011.2415.3001.5331

 

http://www.xdnf.cn/news/19350.html

相关文章:

  • 技术框架之RPC
  • 【系统分析师】高分论文:论信息系统的安全与保密设计
  • c++ 线程局部存储(Thread-Local Storage,TLS)
  • 当服务器报警响起:CPU、内存、磁盘使用率飙升的诊断与处置
  • 基于单片机智能鞋柜/智能鞋橱/智能鞋盒
  • C++项目的Makefile案例解析
  • Python基础之元组列表集合字典
  • Python与Rust语法对比详解:从入门到精通
  • C++顺序嵌套回调函数
  • 飞牛NAS上部署Markdown文稿编辑器,阅读.md文件同时还可以跨平台访问!
  • Qt精华版打包教程,支持windows和Linux,每种平台支持2种方案
  • 电感值过大过小会影响什么
  • AI基础学习周报十一
  • 艾体宝案例 | 数据驱动破局:DOMO 如何重塑宠物零售门店的生存法则
  • HarmonyOS 应用开发:基于API 12+的现代化实践
  • C++从入门到实战(二十)详细讲解C++List的使用及模拟实现
  • Ubuntu安装NVIDIA显卡驱动
  • #Datawhale 组队学习#8月-工作流自动化n8n入门-3
  • LabVIEW 瀑布图与游标操作
  • 分布式事务相关
  • [软考中级]嵌入式系统设计师—核心知识点速记
  • 分布式相关
  • 【iOS】MVC架构
  • 自制扫地机器人(一)20 元级机械自动避障扫地机器人——东方仙盟
  • 晶晨线刷工具下载及易错点说明:生成工作流程XML失败
  • Trie树(静态数组实现)
  • 人工智能加速漏洞利用,15分钟即可完成概念验证?
  • 神州数码VRRP 原理与配置篇
  • 应用开发使用缓存
  • macos调用chrome后台下载wasm-binaries.tar.xz