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

动态链接库(DLL)

一、什么是动态链接库(DLL)?

定义总结:

动态链接库(Dynamic-Link Library,DLL)是一种存放可被多个程序共享,且在运行时按需加载的代码库。在Windows环境中,DLL的扩展名通常是.dll

核心特征:

  • **动态加载:**程序运行时通过系统API(如LoadLibrary)载入DLL。
  • **代码共享:**多个进程可以同时使用同一份DLL,减少内存占用。
  • **功能扩展:**方便程序后续升级,不必重新编译整个程序。

二、C++中如何实现和调用DLL?

1. 设计和导出DLL

  • 在DLL代码中,使用__declspec(dllexport)修饰符导出接口函数:
// MyLib.h
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endifextern "C" {MYLIB_API int add(int a, int b);
}
  • 实现文件:
// MyLib.cpp
#include "MyLib.h"int add(int a, int b) {return a + b;
}
  • 在DLL项目中定义MYLIB_EXPORTS宏,确保符号导出。

2. 在客户端调用DLL

  • 可以静态声明导入,或者动态加载。

静态声明方式(链接时):

// 直接引用头文件,链接对应.lib文件
#include "MyLib.h"int main() {int result = add(3, 5);return 0;
}

动态加载方式(运行时加载):

#include <windows.h>
#include <iostream>typedef int (*AddFunc)(int, int);int main() {HMODULE lib = LoadLibrary(TEXT("MyLib.dll"));if (!lib) {std::cerr << "无法加载DLL" << std::endl;return -1;}AddFunc add = (AddFunc)GetProcAddress(lib, "add");if (!add) {std::cerr << "找不到函数" << std::endl;FreeLibrary(lib);return -1;}std::cout << "3 + 4 = " << add(3, 4) << std::endl;FreeLibrary(lib);return 0;
}

三、优缺点分析

优势劣势
代码复用;节省内存DLL版本控制难,可能产生“DLL地狱”
更新方便,不需要重编译全部程序依赖关系复杂,调试难度增大
支持插件式设计可能引入加载时的安全或性能隐患

四、常见面试问点

  • 导出符号的方式__declspec(dllexport) 和 .def文件。
  • DLL的加载机制:静态加载(链接时)vs 动态加载(运行时)。
  • DLL的生命周期管理LoadLibrary 和 FreeLibrary,以及DLL的引用计数。
  • 跨平台问题:Linux的.so文件类似于Windows的DLL。
  • 版本兼容性问题:如何避免“DLL地狱” – 使用接口版本控制、合理封装。

五、总结要点

  • DLL是实现模块化、重用、升级的基础,同时也是操作系统提供的机制。
  • 在C++中,导出函数和动态加载是其核心使用方式。
  • 开发中要注意DLL的依赖管理和版本控制,避免潜在的运行时错误。

  • 文件形式:

    • 在Windows系统:后缀名通常是.dll(Dynamic-Link Library,动态链接库)
    • 在Linux和类Unix系统:后缀名是.so(Shared Object,共享对象)
  • 内容:

    里面存放了被多个程序共用的代码(函数、数据),比如各种工具和功能。

三、为什么要用动态链接库?——好处和作用

1. 节省空间和资源

多个程序可以共享同一份DLL,不必每个都复制一份。

比如,你的office、浏览器、游戏都用到“打印机驱动”,共享一份DLL文件。

2. 方便更新和维护

升级DLL,不用重新编译所有依赖它的程序,直接替换DLL文件,就能改善功能或修复漏洞。

3. 提高加载效率

只在需要用到的某个功能时,才加载相关DLL,而不是在程序一开始就加载所有代码。

4. 支持插件机制

比如你开发的软件可以支持插件,只需加载对应DLL就可以扩展功能。

四、在C++中,怎么用动态链接库?

这部分是面试的重点,我会拆烧:

1. 创建DLL(被调用者或“提供者”)

在Visual Studio中,通常会做两个文件:

  • 头文件(声明导出的函数)
  • 实现文件(定义函数)

示例:

// MyLib.h
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endifextern "C" {MYLIB_API int add(int a, int b);
}

说明:

  • __declspec(dllexport)是告诉编译器,我要导出这个函数让别人用。

实现:

// MyLib.cpp
#include "MyLib.h"int add(int a, int b) {return a + b;
}

在编译时定义MYLIB_EXPORTS,就会导出add函数。


2. 调用DLL(“使用者”)

方式一:静态链接(导入.lib文件)

  • 编译好了DLL后,还会生成一个对应的.lib文件
  • 客户端直接链接这个.lib文件,在代码中包含头文件,直接调用

方式二:动态加载(运行时加载)

  • 使用系统API(Windows下是LoadLibrary

复制代码

#include <windows.h>
#include <iostream>
typedef int (*AddFunc)(int, int);int main() {HMODULE hLib = LoadLibrary(TEXT("MyLib.dll"));if (!hLib) {std::cout << "加载DLL失败" << std::endl;return -1;}AddFunc add = (AddFunc)GetProcAddress(hLib, "add");if (!add) {std::cout << "找不到函数" << std::endl;FreeLibrary(hLib);return -1;}std::cout << "2 + 3 = " << add(2,3) << std::endl;FreeLibrary(hLib);return 0;
}

这里, LoadLibrary 动态加载DLL,GetProcAddress 获取函数指针,最后调用。


五、常见问题和要点

  • 符号导出

    使用__declspec(dllexport),或者用.def文件定义导出函数。

  • 跨平台差异

    Windows用.dll,Linux用.so,调用API不同,但思想一样。

  • DLL的版本控制

    避免“DLL地狱”——多个版本冲突引发的问题。解决措施:采用接口版本控制,和动态加载通信协议。

  • DLL的生命周期

    使用完毕调用FreeLibrary,避免内存泄漏。

  • 调试难点

    动态库出错时,难以定位问题。可以用工具(如Dependency Walker)检查依赖。


六、总结——“大白话”总结

  • 动态链接库(DLL)就像是公共工具箱,大家都用,同样的工具不用每个人都买一份。
  • 让程序变得更小、易维护,也方便升级。
  • 在写代码时,要导出想让别人用的“功能”,别忘了用特殊的关键词告诉编译器(像__declspec(dllexport))。
  • 调用它,要用系统的API(比如LoadLibraryGetProcAddress)动态加载用。

相关文章:

  • ERP系统源码,有演示,开发文档、数据库文档齐全,支持二次开发
  • C 语言 第五章 指针(7)
  • 1247: 彩色的棋子(chess)
  • 模拟芯片设计中数字信号处理一些常用概念(一)
  • 嵌入式Linux驱动学习
  • 2025年01月03日美蜥(杭州普瑞兼职)二面
  • MyDB - 手写数据库
  • LeetCode 热题 100 118. 杨辉三角
  • 使用 Ingress NGINX 和 NLB 优化 EKS 中多个 Kubernetes 服务的外部和内部访问
  • 【FPGA开发】Xilinx DSP48E2 slice 一个周期能做几次int8乘法或者加法?如何计算FPGA芯片的GOPS性能?
  • c++类【开端】
  • weaviate v1.30.2发布!全方位优化SegmentIndex,RBAC升级兼容,OpenAI集成更智能!
  • MyBatis-Plus 非 Spring 环境使用时 `GenericTypeResolver` 缺失问题总结
  • Auto.js 脚本:清理手机数据但保留账号
  • 林业数智化转型初步设计方案
  • 「Mac畅玩AIGC与多模态19」开发篇15 - 判断节点与工具节点联动示例
  • 二项式反演 系列 题解
  • 【蓝牙协议栈】【BR/EDR】【AVCTP】精讲音视频控制传输协议
  • BUUCTF 大流量分析(一) 1
  • AUTOSAR图解==>AUTOSAR_SRS_CryptoStack
  • 山东滕州一车辆撞向公交站台致多人倒地,肇事者被控制,案件已移交刑警
  • 新闻1+1丨多地政府食堂开放“舌尖上的服务”,反映出怎样的理念转变?
  • 景点变回监狱,特朗普下令重新启用“恶魔岛”
  • 郭旭涛转任河北省科协党组书记、常务副主席,曾任团省委书记
  • 跳水世界杯总决赛陈佳获得女子3米板冠军,陈艺文获得亚军
  • 巴菲特再谈投资日本:希望持有日本五大商社至少50年