没有合适的资源?快使用搜索试试~ 我知道了~
首页VC++动态链接库详解:类型、调用与应用实例
本资源深入探讨了VC++中的动态链接库(DLL)编程,涵盖了静态链接库与动态链接库的区别及其各自的优势。静态链接库,如同一个预先打包的代码仓库,其内容直接嵌入到最终的可执行文件(EXE)中,而动态链接库则允许程序在运行时加载和卸载,提供了代码复用和灵活性。静态链接库不支持包含其他类型的链接库,但动态链接库可以包含动态或静态库。 动态链接库具有跨语言兼容性,不受编程语言和编译器的限制,Windows系统中的系统DLL如kernel32.dll、user32.dll和gdi32.dll就是典型的例子,它们封装了大量的操作系统功能,如内存管理、用户界面控制和图形操作。例如,我们常用的MessageBox函数就是由user32.dll提供的,这表明DLL在日常开发中起着关键作用。 在VC++中,动态链接库有三种类型:Non-MFC DLL(非MFC动态库)主要用于非MFC和MFC应用间的交互,导出的标准C接口函数可供不同环境下的应用程序调用;MFC Regular DLL包含一个继承自CWinApp的类,但不包含消息循环,适合用于特定MFC应用场景;而MFC Extension DLL则是MFC的扩展版本,采用MFC的动态链接特性,功能更为强大。 理解并掌握这些概念对于在VC++中有效地设计和利用动态链接库至关重要,因为它不仅提高了代码的复用性和可维护性,还促进了不同组件之间的松耦合。通过学习如何创建、部署和调用DLL,开发者可以提升软件的性能和可靠性,同时降低总体项目成本。
资源详情
资源推荐
}
分析上述代码,dllTest 工程中的 lib.cpp 文件与第 2 节静态链接库版本完
全相同,不同在于 lib.h 对函数 add 的声明前面添加了__declspec(dllexport)
语句。这个语句的含义是声明函数 add 为 DLL 的导出函数。DLL 内的函数分为两种:
(1)DLL 导出函数,可供应用程序调用;
(2) DLL 内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
而应用程序对本 DLL 的调用和对第 2 节静态链接库的调用却有较大差异,
下面我们来逐一分析。
首先,语句 typedef int ( * lpAddFun)(int,int)定义了一个与 add 函数
接受参数类型和返回值均相同的函数指针类型。随后,在 main 函数中定义了
lpAddFun 的实例 addFun;
其次,在函数 main 中定义了一个 DLL HINSTANCE 句柄实例 hDll,通过
Win32 Api 函数 LoadLibrary 动态加载了 DLL 模块并将 DLL 模块句柄赋给了
hDll;
再次,在函数 main 中通过 Win32 Api 函数 GetProcAddress 得到了所加载
DLL 模块中函数 add 的地址并赋给了 addFun。经由函数指针 addFun 进行了对 DLL
中 add 函数的调用;
最后,应用工程使用完 DLL 后,在函数 main 中通过 Win32 Api 函数
FreeLibrary 释放了已经加载的 DLL 模块。
通过这个简单的例子,我们获知 DLL 定义和调用的一般概念:
(1)DLL 中需以某种特定的方式声明导出函数(或变量、类);
(2)应用工程需以某种特定的方式调用 DLL 的导出函数(或变量、类)。
下面我们来对“特定的方式进行”阐述。
4.2 声明导出函数
DLL 中导出函数的声明有两种方式:一种为 4.1 节例子中给出的在函数声明
中加上__declspec(dllexport),这里不再举例说明;另外一种方式是采用模块
定义(.def) 文件声明,.def 文件为链接器提供了有关被链接程序的导出、属性
及其他方面的信息。
下面的代码演示了怎样同.def 文件将函数 add 声明为 DLL 导出函数(需在
dllTest 工程中添加 lib.def 文件):
; lib.def : 导出 DLL 函数
LIBRARY dllTest
EXPORTS
add @ 1
.def 文件的规则为:
(1)LIBRARY 语句说明.def 文件相应的 DLL;
(2)EXPORTS 语句后列出要导出函数的名称。可以在.def 文件中的导出函数
名后加@n,表示要导出函数的序号为 n(在进行函数调用时,这个序号将发挥
其作用);
(3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能
与语句共享一行。
由此可以看出,例子中 lib.def 文件的含义为生成名为“dllTest”的动态
链接库,导出其中的 add 函数,并指定 add 函数的序号为 1。
4.3 DLL 的调用方式
在 4.1 节的例子中我们看到了由“LoadLibrary-GetProcAddress-
FreeLibrary”系统 Api 提供的三位一体“DLL 加载-DLL 函数地址获取-DLL 释
放”方式,这种调用方式称为 DLL 的动态调用。
动态调用方式的特点是完全由编程者用 API 函数加载和卸载 DLL,程序员
可以决定 DLL 文件何时加载或不加载,显式链接在运行时决定加载哪个 DLL
文件。
与动态调用方式相对应的就是静态调用方式,“有动必有静”,这来源于
物质世界的对立统一。“动与静”,其对立与统一竟无数次在技术领域里得到验
证,譬如静态 IP 与 DHCP、静态路由与动态路由等。从前文我们已经知道,库也分
为静态库与动态库 DLL,而想不到,深入到 DLL 内部,其调用方式也分为静态与
动态。“动与静”,无处不在。《周易》已认识到有动必有静的动静平衡观,《易.
系辞》曰:“动静有常,刚柔断矣”。哲学意味着一种普遍的真理,因此,我们
经常可以在枯燥的技术领域看到哲学的影子。
静态调用方式的特点是由编译系统完成对 DLL 的加载和应用程序结束时
DLL 的卸载。当调用某 DLL 的应用程序结束时,若系统中还有其它程序使用该
DLL,则 Windows 对 DLL 的应用记录减 1,直到所有使用该 DLL 的程序都结束时
才释放它。静态调用方式简单实用,但不如动态调用方式灵活。
下面我们来看看静态调用的例子(单击此处下载本工程附件),将编译
dllTest 工程所生成的.lib 和.dll 文件拷入 dllCall 工程所在的路径,dllCall
执行下列代码:
#pragma comment(lib,"dllTest.lib")
//.lib 文件中仅仅是关于其对应 DLL 文件中函数的重定位信息
extern "C" __declspec(dllimport) add(int x,int y);
int main(int argc, char* argv[])
{
int result = add(2,3);
printf("%d",result);
return 0;
}
由上述代码可以看出,静态调用方式的顺利进行需要完成两个动作:
(1)告诉编译器与 DLL 相对应的.lib 文件所在的路径及文件名,#pragma
comment(lib,"dllTest.lib")就是起这个作用。
程序员在建立一个 DLL 文件时,连接器会自动为其生成一个对应的.lib 文
件,该文件包含了 DLL 导出函数的符号名及序号(并不含有实际的代码)。在
应用程序里,.lib 文件将作为 DLL 的替代文件参与编译。
(2)声明导入函数,extern "C" __declspec(dllimport) add(int x,int
y)语句中的__declspec(dllimport)发挥这个作用。
静态调用方式不再需要使用系统 API 来加载、卸载 DLL 以及获取 DLL 中导出
函数的地址。这是因为,当程序员通过静态链接方式编译生成应用程序时,应用
剩余52页未读,继续阅读
宇白
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 构建Cadence PSpice仿真模型库教程
- VMware 10.0安装指南:步骤详解与网络、文件共享解决方案
- 中国互联网20周年必读:影响行业的100本经典书籍
- SQL Server 2000 Analysis Services的经典MDX查询示例
- VC6.0 MFC操作Excel教程:亲测Win7下的应用与保存技巧
- 使用Python NetworkX处理网络图
- 科技驱动:计算机控制技术的革新与应用
- MF-1型机器人硬件与robobasic编程详解
- ADC性能指标解析:超越位数、SNR和谐波
- 通用示波器改造为逻辑分析仪:0-1字符显示与电路设计
- C++实现TCP控制台客户端
- SOA架构下ESB在卷烟厂的信息整合与决策支持
- 三维人脸识别:技术进展与应用解析
- 单张人脸图像的眼镜边框自动去除方法
- C语言绘制图形:余弦曲线与正弦函数示例
- Matlab 文件操作入门:fopen、fclose、fprintf、fscanf 等函数使用详解
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功