正文

第十八课:动态链接库2007-09-26 19:03:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lym51/29685.html

分享到:

第十八课:动态链接库 一、概念: 1、  静态链接库: 应用程序从函数库中得到所的函数的执行代码,然后把招生代码自身的执行文件中,应用程序在运行时,不再需要函数库的支持。 2、  动态链接库: 应用程序的中不包含函数库中的函数的执行代码,编译和连接时只是包含包含它们的参考,运行时再将它们的执行代码加入内存,所以在程序运行时需要函数的支持。 二、编写DLL: 建立一个Windows Dynamic-Link Library,选择建一个An Empty Dll Project,加入一个CPP文件, int add(int x,int y) { return x+y; } extern "C" _declspec (dllexport) int add3(int x,int y,int z) {         return add(x,y)+z; } 说明: 1.  Add是一个供DLL中其它函数调用的函数, Add3是DLL提供给其它应用程序调用的函数。 2.  当DLL中含有输出函数时,编译DLL时会生成DLL文件和LIB文件。LIB文件称为DLL的导入库,它是一个特殊的库文件。它不包含执行代码,只是用来提供给链接器关于DLL函数在DLL中的入口信息,从而使得可执行程序 中也不会包含所调用DLL函数 的代码 ,只保留对DLL函数的动态链接参考。 3.  导出函数的两种方法: a.  使用微软专用的_declspec (dllexport):(如上面的例子) cpp文件在编译为OBJ文件时要对函数进行重新命名,C语言会把函数name重新命名为_name,而C++会重新命名为_name@@decoration, extern "C"表示用C语言的格式将函数重命名。 b.  使用模块定义文件: 模块定义文件即DEF文件,是包含一个或多个模块定义语句的文本文件,用来描述动态链接库的各种属性。 一个最小的·DEF文件包括以下模块定义语句: l         第一条语句必须是LIBRARY语句,用来说明动态链接库的名字。 l         有EXPORTS语句之后列出动态链接库要输出的函数。用户可以在每个要输出的函数指定一个输出序列号,这只要在对应的函数名之后 加上@符号心腹一个数字即可。注意:这个数字应该是从1到输出函数总数之间的没有重复的数字。指定函数的序列号后,动态加载该函数时,就会通过序列号而不是函数名来检索该函数,因此处理速度将会加快,战胜的内存会减少,从而增加动态链接时的效率。 将上面的例子改为用DEF文件输出: int add(int x,int y) {      return x+y; } extern "C"  int add3(int x,int y,int z) {         return add(x,y)+z; } 在工程中加入一文本文件,其名字为dll.def,加入以下语句:      LIBRARY       dll EXPORTS        add3              @    1 三、访问动态链接库: 新建一个基于对话框的MFC工程, 1.  静态调用: 通过编译器提供给应用程序关于DLL的名称,以及DLL函数的链接参考。这种方式不需要在程序中用代码将DLL加载到内存。 a.  将DLL和LIB文件拷贝到工程目录下,最好在工程的DEBUG目录下也拷贝一份。 b.  在ProjectàSettingsàLink中的Object/Library Modules:填入LIB文件的名字。本例中是dll.lib。 c.  在对话框中加入一个按钮控件,添加它的响应函数OnButton1(),在其中加入调用代码:        CString str;        str.Format("%d",add3(3,4,5));        MessageBox(str); d.  加入函数声明: l         用_declspec (dllexport)导出函数的DLL extern "C"_declspec (dllimport) int add3(int x,int y,int z); l         用DEF文件导出函数的DLL int add3(int x,int y,int z); 2.  动态调用: 在程序中用语句显式地加载DLL,编译器不需要知道任何关于DLL的信息。 a.  将DLL文件拷贝到工程目录下,最好在工程的DEBUG目录下也拷贝一份。 b.  在对话框中加入一个按钮控件,添加它的响应函数OnButton1(),在其中加入调用代码: CString str; typedef int (*PADD3)(int x,int y,int z);                      //定义一种新的数据类型—指向函数的指针 PADD3 add3; HINSTANCE hDll=LoadLibrary("dll");                 //将动态链接库加载到内存 add3=(PADD3)GetProcAddress(hDll,"add3");                //得到DLL中指定函数的指针 str.Format("%d",add3(3,4,5)); MessageBox(str); FreeLibrary(hDll);//释放应用程序对DLL的控制权               说明:如果DLL用DEF文件导出函数时为其指定了序列号,比如1,则                             add3=(PADD3)GetProcAddress(hDll,"add3");                        可以改为:                 add3=(PADD3)GetProcAddress(hDll, MAKEINTRESOURCE(1)); 四、其它: 1.  Windows如何定位DLL 不论是静态调用还是动态调用DLL,Windows会按以下顺序寻找DLL: a.  当前路径 b.  Windows的system路径。用API函数GetSystemDirectory可以得到; c.  Windows路径。用API函数GetWindowsDirectory可以得到; d.  环境变量PATH所指定 的路径。 2.  DLL也可以有一个入口函数DllMain(),当然也可以没有。如果有,DllMain会在进程加载、进程缷载、线程加载和线程缷载DLL时自动调用。 3.  为了用户使用方便,应该将导出函数的声明放在一个头文件中。可以使用预处理命令简化更换__declspec(dllexport)和__declspec(dllimport)的操作。这样,DLL和应用程序 可以使用相同的头文件: #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif

阅读(9239) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册