动态链接库是基于提高系统内存资源的使用效率的解决办法。
为提高内存资源的使用效率,每一个程序都应该尽量少占用内存空间,在多任务环境下,同时运行的多个应用程序有时要调用相同的函数(尤其是一些统一的接口),比如标准的数学函数和windows环境下的窗口维护函数等等。因此,设想当多个应用程序同时运行并且都调用同一个函数时,不应该在内存上生成这个函数的多份拷贝,而应该使这些程序能够共享这个函数在内存中的执行代码,这样就减少了程序对内存的占用。动态连接库就是这样的具体实现办法。
1. DLL 介绍
动态链接库(Dynamic Link Library, DLL)是一个包含了若干个导出函数的可执行文件。与静态连接库(SLL)类似,DLL本质上也是一个函数库。但是与前者的主要区别是库代码的链接时机。如名字所理解,SLL是在编译、链接程序时就同程序链接,DLL则是在程序运行时才同程序链接;前者通过链接器LINK完成,后者由Windows操作系统(程序的运行者/管理者/载体)完成。
此外,SLL是直接把库里面的可执行代码直接复制到应用程序中,这样就增加了程序最终的可执行代码长度。SLL在多任务环境下运行效率可能很低,比如,两个程序同时运行且调用了库内的同一个函数,那么内存中就存在该函数的两个副本,从而降低了内存的使用效率。
DLL并不是这样,它不复制代码到程序中,而是通过动态加载,DLL代码被映像到调用进程的地址空间。DLL允许多个程序共享某个函数的一个副本。无论被多少个程序调用,在内存中只允许该函数的一个副本。
2. DLL 功能
除了实现代码的共享,还能实现资源的共享。DLL具有模块封装特性,只要导出的函数名相同,程序运行同一个DLL的不同版本不需要编译和链接。所以这使得产品在升级或更新时,客户程序无需进行修改。
3. 创建DLL
参考文章: http://www.programgo.com/article/55561174797/
https://msdn.microsoft.com/zh-cn/library/1ez7dh12.aspx
//比如在创建的动态链接库Mymfcdll的源文件Mymfcdll.cpp中定义一个导出函数对动态连接库项目Mymfcdll进行编译、链接就生成了动态链接库Mymfcdll.dll和导入库文件Mymfcdll.lib。将这个dll文件复制到windows的system子目录下,lib文件复制到要调用这个DLL的应用程序的DEBUG目录下,程序就能自动调用Mymfcdll.dll的导出函数GetDateAndTime()并正确编译、链接、运行【隐式链接】。
_declspec(dllexport) char * WINAPI GetDateAndTime()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // 必须在函数的第1条语句位置处添加AFX_MANAGE_STATE宏
// 函数功能
char * szDateTime;
struct tm *newtime;
time_t long_time;
time(&long_time);
newtime=localtime(&long_time);
szDateTime=asctime(newtime);
return szDateTime;
}
// 在头文件Mymfcdll.h中添加导出函数声明,必须使用导出关键字_declspec(dllexport)
// 导出函数GetDateAndTime()的声明
_declspec(dllexport) char * WINAPI GetDateAndTime();
4. 使用DLL
分为隐式链接和显式链接。
隐式链接:在程序运行时,由windows操作系统将要使用的DLL自动加载到应用程序,这种方式:除了DLL,还要有DLL的导入库文件(LIB文件),并且需要在VC++ IDE中设置Project的有关选项。
显式链接:程序在执行过程中,程序本身通过专门的函数(如LoadLibrary)调用来动态加载相应的DLL。
使用示例:
依照上例,比如在应用程序的CMainFrame类中调用导出函数GetDateAndTime()
void CMainFrame::OnDateandTime()在MainFrame.h文件中类CMainFrame定义之前将函数GetDateAndTime()声明为外部定义的函数,以便正确编译和链接:
{
char * szDT;
szDT = GetDateAndTime();//调用上例中创建的Mymfcdll动态链接库的函数GetDateAndTime
AfxMessageBox(szDT,MB_OK,0);
}
extern char * WINAPI GetDateAndTime();
class MainFrame::public CFrameWnd
{
...
}
显式链接: