孙鑫-MFC笔记十一--动态链接库
来源:互联网 发布:软件编程职业培训 编辑:程序博客网 时间:2024/04/29 23:49
Windows三个重要的动态链接库
Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;
User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;
GDI32.dll,它包含用于画图和显示文本的各个函数。
静态库和动态库区别:
静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件);
在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行时候,再去加载DLL,访问DLL中导出的函数。这个引入库也是lib格式,但其与静态库不同。
使用动态链接库的好处
可以采用多种编程语言来编写。
增强产品的功能。
提供二次开发的平台。
简化项目管理
可以节省磁盘空间和内存。
有助于资源的共享。
有助于实现应用程序的本地化
动态链接库加载的两种方式:
隐式连接
显示加载
隐式连接:
建立DLL文件代码如下:
_declspec(dllexport) int Add(int x,int y)
{
}
_declspec(dllexport) int Subtract(int x,int y)
{
}
//必须带_declspec(dllexport)文件,以生成*.lib文件
必须被到处的函数,可以用dumpbin工具查看那些函数是导出的。要到处的函数,前面加上标识符:_declspec(dllexport)
如果要查找*dll中包含信息,可在命令行下进入Debug所在目录,输入以下命令
dumpbin -exports dll.dll
有些时候由于某种安装原因,dumpbin被认为是无效命令,接下来在
C:\Program Files\Microsoft Visual Studio\VC98\Bin\下找到VCVARS32.bat并在命令行运行,之后就能执行dumpbin命令了。
C++名字改编 或者叫名字粉碎
隐式连接方式:
下面是测试文件:
新建MFC程序,新建两个按钮,代码如下:
void CDllTestDlg::OnBtnAdd()
{
}
void CDllTestDlg::OnBtnSubtract()
{
}
为使编译器认识Add,Subtract,必须在之前使用两个声明:
extern int Add(int x,int y);
extern int Subtract(int x,int y);
可以使用标示符表示这两个函数是从动态链接库的.lib文件引用的,以生成效率更高的代码
_declspec(dllimport) int Add(int x,int y);
_declspec(dllimport) int Subtract(int x,int y);
这两段代码我们也可以在DLL中新建一个头文件放进去,并在MFC程序中添加头文件
如#include "..\Dll\Dll.h"
从原先Dll文件下Debug目录中复制*.lib到MFC程序文件夹下,并添加库函数
在project--->setting--->link--->Object/Library Modules写下所复制的文件名
如果要查看DllTest.exe文件信息,使用命令行dumpbin -imports dlltest.exe
修改动态链接库Dll.h
#ifdef DLL_API
#else
#define DLL_API _declspec(dllimport)
#endif
DLL_API int Add(int x,int y);
DLL_API int Subtract(int x,int y);
修改Dll.cpp文件
#define DLL_API _declspec(dllexport)
#include "Dll.h"
int Add(int x,int y)
{
}
int Subtract(int x,int y)
{
}
这样做是为了方便外部程序调用同时方便内部程序使用,因为动态链接库中只有导出的函数才可以被使用,没有导出的函数在外部是看不到的,是不能被访问的
接下来导出整个类,代码:
class DLL_API point
{
public:
};仍然受制于访问权限
实现:
void Point::output(int x,int y)
{
}
接下来在MFC程序新建一个按钮,调用动态链接库函数,代码如下:
因为C++导出或导入动态链接库会发生名字的改编,如果不想发生名字改编,我们可以使用如下代码:
#define DLL_API
这样编译器就不会进行名字改编,一个用C语言编写的客户端程序就可以调用这个用C++编写的动态链接库。其缺点是,不能导入类中的成员函数
如果导出函数的调用约定,发生变化,即时使用了限定符,函数的名字也会发生变化。
如果函数使用标准调用约定_stdcall,即使使用了extern "c",此函数仍会发生改编
在这种情况下,通过DEF,模块定义文件的方式来解决问题。
接下来新建一个动态链接库文件,文件名为Dll2,cpp文件代码为:
int Add(int x,int y)
{
}
int Subtract(int x,int y)
{
}
为了最终解决问题,我们可以新建一个模块文件Dll.def,以使得其他语言编制的程序也能使用我们的动态链接库。
添加代码
LIBRARY Dll2 //内部名称,与生成的动态链接库名称要匹配。非必须代码
EXPORTS
Subtract
EXPORTS 语句引入了一个由一个或多个 definitions(导出的函数或数据)组成的节。每个定义必须在单独一行上。EXPORTS 关键字可以在第一个定义所在的同一行上或在前一行上。.def 文件可以包含一个或多个 EXPORTS 语句。
导出 definitions 的语法为:
entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]
entryname 是要导出的函数名或变量名。这是必选项。如果导出的名称与 DLL 中的名称不同,则通过 internalname 指定 DLL 中导出的名称。例如,如果 DLL 导出函数 func1(),要将它用作 func2(),则应指定:
EXPORTS
func2=func1
@ordinal 允许指定是序号而不是函数名将进入 DLL 的导出表。这有助于最小化 DLL 的大小。.LIB 文件将包含序号与函数之间的映射,这使您得以像通常在使用 DLL 的项目中那样使用函数名。
可选的 NONAME 关键字允许只按序号导出,并减小结果 DLL 中导出表的大小。但是,如果要在 DLL 上使用 GetProcAddress,则必须知道序号,因为名称将无效。
可选的 PRIVATE 关键字禁止将 entryname 放到由 LINK 生成的导入库中。它对同样是由 LINK 生成的图像中的导出无效。
可选的 DATA 关键字指定导出的是数据,而不是代码。例如,可以导出数据变量,如下所示:
EXPORTS
i DATA
显示加载:
接下来在MFC文件中改写按钮void CDllTestDlg::OnBtnAdd() 代码:
/*
HMODULE LoadLibrary(
);
LoadLibrary不仅可以加载动态连接库,还可以加载exe文件。
//如果在DLL的函数中调用_stdcall,相应的应该把代码改为
//typedef int (_stdcall *ADDPROC)(int a,int b);
/*
得到导出函数的地址
FARPROC GetProcAddress(
);
因为调用LoadLibrary时动态加载动态链接库,所以不需要头文件和.lib文件
如果我们在动态链接库中使用标准调用约定_stdcall,而在可执行程序中使用动态加载DLL,会发生名字重编,如果知道DLL中函数的序号,这时可以使用宏MAKEINTRESOURCE把序号转变成名字,如:
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));
/*
The MAKEINTRESOURCE macro converts an integer value to a resource type compatible with the resource-management functions. This macro is used in place of a string containing the name of the resource.
Syntax
LPTSTR MAKEINTRESOURCE(
);
*/
DllMain 是个可选的入口函数。
BOOL WINAPI DllMain(
);
DllMain函数,不要做太复杂的调用,因为,在加载动态链接库的同时,可能还需要一些核心的动态链接库没有被加载。而程序会依次加载调用的Dll。我们自己的Dll可能会被考前加载,调用重要函数失败,导致程序终止。
当我们的动态链接库不再使用时可以调用FreeLibrary使动态链接库使用计数减1,当使用计数为零时,系统会收回模块资源
FreeLibrary
The FreeLibrary function decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.
BOOL FreeLibrary(
);
- 孙鑫-MFC笔记十一--动态链接库
- MFC 动态链接库
- mfc动态链接库
- MFC:动态链接库
- MFC动态链接库
- MFC动态链接库
- MFC(动态链接库编程,孙鑫C++第十九讲笔记整理)
- MFC- 动态链接库编程(孙鑫-第十九讲笔记整理)
- MFC使用动态链接库
- 动态链接库笔记
- 动态链接库 笔记
- MFC动态链接库和WIN32动态链接库
- MFC动态链接库和WIN32动态链接库
- MFC动态链接库和WIN32动态链接库
- MFC动态链接库和WIN32动态链接库
- MFC动态链接库和WIN32动态链接库
- Win32动态链接库和MFC 动态链接库
- 孙鑫MFC第十九章 动态链接库编程
- Qt初体验
- 磁珠的作用
- 多线程之四 一个经典的多线程同步问题
- 超级隐蔽的小说阅读器
- Java医药桌面系统w
- 孙鑫-MFC笔记十一--动态链接库
- fstream详解
- matlab在终端显示有颜色的字(cprintf函数的用法)
- Android source build/envsetup.sh学习笔记
- 21个电脑小技巧
- Doubango 定时器管理用法
- Web页面制作基础(一)
- 多线程之五 经典线程同步 关键段CS
- Linux/hp unix/AIX日常巡检脚本