正文

第19课 DLL编程2007-05-01 15:40:00

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

分享到:

1.DLL简介,动态库,静态库。动态库节约磁盘空间,静态库体积大。可以用多种语言编写DLL文件。动态库有两种加载方式:隐式调用和动态加裁!2.新建一个DLL1的dll工程,加入一源文件名为dll1.cpp,加入add和subtract两个函数,注意此时须在函数名前加_declspec(dllexport),并且编译。用dumpbi -exports dll1.dll查看其导出的函数,发现函数名字已经被改成了 ?add@@YAHHH@Z,这种现象叫做名字粉碎,是为了支持函数重载而做的。3.编写一个程序测试DLL,工程名为DllTest,基于对话框的,放置两个按纽add和subtract,响应按纽消息,调用这个Dll的add和subtract函数。使用这两个函数前要先声明函数,//extern int add(int a,int b);//extern int subtract(int a,int b);还需要将Dll1.lib和Dll1.dll拷贝到当前目录下!另外还需要在Project->Setting->Link->Object/Library中加入Dll1.lib,此种方式为隐式调用!OK!用Dumpbin -imports DllTest.exe查看它的输入信息,可以看到它加亓薲ll1.dll。同时也可以用depends程序查看程序需要哪些dll文件!除了用extern外,还可以用//_declspec(dllimport) int add(int a,int b);//_declspec(dllimport) int subtract(int a,int b);告诉编译器,此函数是动态链接库中的函数,这样可以提高效率。4.通常写Dll时在dll1.h中声明函数,然后在DllTest.h中包含这个头文件,另外会用一组宏来取代_declspec(dllimport)Dll1.h#ifdef DLL1_API#else#define DLL1_API extern "C" _declspec(dllimport)#endif DLL1_API int _stdcall add(int a,int b);DLL1_API int _stdcall subtract(int a,int b);Dll1.cpp的代码:#define DLL1_API extern "C" _declspec(dllexport)#include "Dll1.h"#include <Windows.h>#include <stdio.h> int _stdcall add(int a,int b){return a+b;} int _stdcall subtract(int a,int b){return a-b;}5.在Dll1中加入类Point它有一个函数output(int a,intb),它的功能是在屏幕上输出x,y值。须包含头文件windows.h和stdio.h.然后在DllTest中加入一个按纽来测试这个函数!此时我们可以dumpbin来查看dll1.dll和dllTest.exe的导出导入情况。注意,也可以只导出类的某个函数。6.我们希望导出的函数名不被改变,加extern "C"大写的C!即可,#define DLL1_API extern "C" _declspec(dllexport),但它只能导出全局函数,不能导出类的成员函数,并且如果调用约定被改成了别的方式,此时函数名也被改变。所以这种方式不太好。7.解决之道是用模块定义文件。  1.新建dll2.dll工程;  2.加dll2.cpp中写两个函数add和subtract  3.在目录中新建dll2.def文件,增加到工程。  4.在dll2.def中加入如下代码:LIBRARY Dll2 EXPORTSaddsubtract   5.编译后用dumpbin查看函数名是否被改变?   6.测试,我们这次用动态加载的方法来调用dll文件。以前是用隐式链接的方法,嘿嘿。动态加载的好处是需要时再加载,可以提高执行的效率。代码如下:HINSTANCE hInst;hInst=LoadLibrary("Dll3.dll");typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"?add@@YAHHH@Z");ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));if(!Add){  MessageBox("获取函数地址失败!");  return;}CString str;str.Format("5+3=%d",Add(5,3));MessageBox(str);FreeLibrary(hInst);    7.此时你改变调用约定,函数名不会被改变,但如果你加上_stdcall定义函数,调用时也需要加入_stdcall,否则会出错!8.DllMain()是Dll的入口点,不过不是必须的。但在DllMain中不要做复杂的调用。为什么?因为DllMain加载时,某些核心Dll文件不一定已经被加载。9.创建一个基于MFC的DLL工程,简介。10.当不使用DLL时,调用FreeLibrary减少DLL的使用计数,释放DLL资源,减少系统负担。明白?11.上面总结:1.*.def使函数名不改变;             2.定义时为_stdcall,调用时也必须用_stdcall.

阅读(2720) | 评论(0)


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

评论

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