VC动态链接库(DLL)编程
VC编写DLL几种方法的简介+

动态连接库最大的特点就是能节省磁盘空间.当多个进程共享同一个DLL的时候,内存中只有一个DLL的代码.通过映射来使各个进程得以调用.1.用VC建立一个WIN32 DLL我们利用VC编写DLL有几种方法.如果用VC建立一个WIN32 DLL 工程.那这个工程就应该只导出C++的类或全局变量.和全局函数.方法就是在CPP文件中编写你的代码,为每个需要导出的元素进行导出办法是增加如下语句:_declspec(dllexport)你当然可以把它定义成宏例如,如果是一个类STUDENT需要导出, 那么声明时应该是这样写class _declspec{dllexport) student;当然也可以定义时直接导出.我们的客户端,也就是我们调用该函数的客户程序,就需要导入这个类或者函数..填写如下语句:class _declspec(dllimport) student{} // 声明之后就可以利用STUDENT来构造对象,也可以调用它的成员函数..了记住,一定要把工程的连接设置好.要把生成的LIB文件填写好,因为客户程序要想加载DLL,能够准确的调用各个DLL中的函数,都是靠这个LIB文件哪.包括函数的地址等等.当然也可以显示连接利用LOADLIBRARY原型是HMODULE LoadLibrary( LPCTSTR );返回的HMODULE就是一个DLL句柄.所以我们在利用这个句柄来作为参数调用另一个函数GETPROCADDRESSFARPROC GetProcAddress( HMODULE , LPCSTR); //如果利用序号来索引,那么要加上MAKEINTERSOURCE宏返回一个函数指针,利用它来调用函数,LPCSTR是函数名,但你应该利用DUMPBIN来查看一下你导出的函数名,因为C++编译器支持重载,它会以自己的方式重命名.除非你用extern \"C\"用C语言的方式来命名函数.例如一个函数void fun();导出格式应该是extern \"C\" _declspec(dllexport) void fun(); //如果是声明导入函数,直接写原型,如果是声明类,那么一定要是类的头文件声明,包含了成员函数和数据成员的.注意即使是采用了C语言命名方式如果你改变了调用方式_stdcall 那么还是会改变函数命名的,除非你利用DEF文件来导出.EXPORTSfun这样是可以的.2.建立一个MFC扩展DLL扩展DLL是为了更好的支持MFC的类.你建立这个工程后会自动生成一些代码,不要管它先,你把你要动态连接的CPP和相应的.H文件加入到工程,在.CPP文件中需要导出的类上加上AFX_EXT_Class 在.H需要导入的类上加上同样的代码,这样就可以了.例如class AFX_EXT_CLASS CSTUDENT : public CPERSON //.CPP{}class AFX_EXT_CLASS CSTUDENT ; //.H{} //声明3.建立一个常规的DLL如果你要建立扩展的DLL,那么其他的IDE是无法利用的,因为每个编译器的命名方式是不同的.如果你想使其他IDE来调用VC的DLL,那么就建立一个常规的DLL.建立工程以后,编写你要导出的类.例如extern \"C\" _declspec(dllexport) void fun(){AFX_MANAGE_STA TE(AfxGetStaticModuleState( ));}在为每一个需要导出的函数的开头加上这条语句. [Page]在客户端要加上导入语句就可以了.。
VC 动态链接库(DLL)编程

VC++动态链接库(DLL)编程(一)――理解库1.概论先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL 看成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。
在仓库的发展史上经历了“无库-静态链接库-动态链接库”的时代。
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。
但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
对动态链接库,我们还需建立如下概念:(1)DLL的编制与具体的编程语言及编译器无关只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。
譬如Windows提供的系统DLL(其中包括了Windows的API),在任何开发环境中都能被调用,不在乎其是Visual Basic、Visual C++还是Delphi。
(2)动态链接库随处可见我们在Windows目录下的system32文件夹中会看到kernel32.dll、user32.dll和gdi32.dll,windows的大多数API都包含在这些DLL中。
kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。
一般的程序员都用过类似MessageBox的函数,其实它就包含在user32.dll这个动态链接库中。
由此可见DLL对我们来说其实并不陌生。
(3)VC动态链接库的分类Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
VC++动态链接库(DLL)编程深入浅出

VC++动态链接库(DLL)编程深入浅出
2、静态链接库 对静态链接库的讲解不是本文的重点,但是在具体讲解 DLL 之前,通过一个静态链接
库的例子可以快速地帮助我们建立“库”的概念。
图 1 建立一个静态链接库
如图 1,在 VC++6.0 中 new 一个名称为 libTest 的 static library 工程(本工程附件 libTest.zip),并新建 lib.h 和 lib.cpp 两个文件,lib.h 和 lib.cpp 的源代码如下:
下面的代码演示了怎样同.def 文件将函数 add 声明为 DLL 导出函数(需在 dllTest 工程 中添加 lib.def 文件):
; lib.def : 导出 DLL 函数
LIBRARY dllTest
EXPORTS
add @ 1
.def 文件的规则为:
(1)LIBRARY 语句说明.def 文件相应的 DLL;
下面我们来对“特定的方式进行”阐述。
VC++动态链接库(DLL)编程出函数的声明有两种方式:一种为 4.1 节例子中给出的在函数声明中加上 __declspec(dllexport),这里不再举例说明;另外一种方式是采用模块定义(.def) 文件声明,.def 文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
图 3 库的调试与“运行” 通常有比上述做法更好的调试途径,那就是将库工程和应用工程(调用库的工程)放置 在同一 VC 工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点, 执行后按下 F11,这样就单步进入了库中的函数。第 2 节中的 libTest 和 libCall 工程就放在 了同一工作区,其工程结构如图 4 所示。
VC中使用动态链接库DLL

VC中使用动态链接库DLL:静态调用和动态调用2010-05-02 15:56VC中生成DLL的办法见:/KB/DLL/RegDLL.aspx--------------------------------------VC中使用DLL/c1230v/articles/1401448.html调用DLL有两种方法:静态调用和动态调用.(一).静态调用其步骤如下:1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下;2.把你的youApp.lib拷到你目标工程(需调用youApp.DLL的工程)目录下;3.把你的youApp.h(包含输出函数的定义)拷到你目标工程(需调用youApp.DLL的工程)目录下;4.打开你的目标工程选中工程,选择Visual C++的Project主菜单的Settings菜单;5.执行第4步后,VC将会弹出一个对话框,在对话框的多页显示控件中选择Link页。
然后在Object/library modules输入框中输入:youApp.lib6.选择你的目标工程Head Files加入:youApp.h文件;7.最后在你目标工程(*.cpp,需要调用DLL中的函数)中包含你的:#include "youApp.h"注:youApp是你DLL的工程名。
(二).动态调用其程序如下:动态调用时只需做静态调用步骤1.01 {02 HINSTANCE hDllInst = LoadLibrary("youApp.DLL");03if(hDllInst)04 {05typedef DWORD (WINAPI *MYFUNC)(DWORD,DWORD);06 MYFUNC youFuntionNameAlias = NULL;07// youFuntionNameAlias 函数别名08 youFuntionNameAlias = (MYFUNC)GetProcAddress(hDllInst,"youFuntionName"); 09// youFuntionName 在DLL中声明的函数名10if(youFuntionNameAlias)11 {12 youFuntionNameAlias(param1,param2);13 }14 FreeLibrary(hDllInst);15 }16 }显式(静态)调用:LIB + DLL + .H,注意.H中dllexport改为dllimport隐式(动态)调用:DLL + 函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary--------------------------------------动态链接库DLL的链接/mmycly/archive/2006/06/15/917076.aspx应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接。
使用vs建立动态链接库dll过程和使用方法

使用vs建立动态链接库dll的过程和使用方法创建动态链接库(DLL)的过程可以分为几个步骤。
我将使用Visual Studio 来演示这个过程:创建DLL的步骤:1.打开Visual Studio,选择“文件”->“新建”->“项目”。
2.在新项目窗口中,选择“Visual C++”->“Windows桌面向导应用程序”。
3.输入项目名称和位置,然后点击“确定”。
4.在“解决方案资源管理器”中,右键单击项目名称->添加->新建项。
5.在“添加新项”窗口中,选择“DLL”,输入DLL名称,然后点击“添加”。
编写DLL代码:现在你已经有了一个空的DLL,你可以开始编写你的代码了。
例如,你可以添加以下代码到你的.cpp文件中:在这个例子中,我们创建了一个简单的函数add,它接收两个整数并返回它们的和。
extern "C"部分告诉编译器使用C链接规则创建导出函数,__declspec(dllexport)部分使得该函数可以从DLL中导出。
编译和生成DLL:在Visual Studio中,你可以通过点击“生成”菜单然后选择“生成解决方案”来编译和生成你的DLL。
如果编译成功,你可以在你的项目文件夹的Debug或Release 文件夹中找到生成的DLL文件。
使用DLL:使用DLL的过程可以分为几个步骤:1.加载DLL:使用Windows API函数LoadLibrary可以加载DLL。
例如:HMODULE hMod = LoadLibrary(TEXT("MyDLL.dll"));。
这个函数会返回一个模块句柄,如果DLL加载成功的话。
2.获取函数地址:使用GetProcAddress函数可以获取DLL中函数的地址。
例如:add_proc = (int (*)(int, int))GetProcAddress(hMod, "add");。
C语言动态链接库编程

C语言动态链接库编程VB6中引用VC6编写的.DLL函数进行屏幕绘图一、动态链接库的基本概念动态链接库(Dynamic Link Library,简称DLL)是由函数对象以及资源组成的二进制库文件,此库文件能同时被多个进程或者应用程序使用。
图1、VB6中使用.dll库函数在窗体中绘制简单飞机模型上图1展现了在VB6中调用VC6建立的屏幕绘图动态链接库(.DLL)的应用效果,程序的运行非常顺畅;实现了在VB中绘图象在VC中一样的效果(3D+消隐+光照)。
二、动态链接库不可少的两个文件1. 创建动态库的函数源文件(.cpp):编写库函数源码的源文件。
2. 导出函数名字的文件(.def):编写Lib(*.dll)入口函数名字的源文件。
三、编程创建动态链接库下面以简单的屏幕绘图函数为例,实现用VC6创建动态链接库,在VB6中调用(.dll)函数的全过程。
1. 打开VC6:文件-新建-工程(空工程)图2、新建Win32 DLL工程2. 添加(.cpp)文件到工程(Graph.cpp)图3、新建Graph.cpp文件并添加到工程3. 添加(.def)文件到工程(Graph.def)图4、新建Graph.def文件并添加到工程4.在Graph.cpp文件中编写函数源码#ifndef WIN32GDI_API#define WIN32GDI_API _declspec(dllexport)#define EXC extern "C"#define CALL _stdcall#endif#include <windows.h>#include <stdio.h>#include <math.h>typedef struct _tagSIZE2I{int width;int height;}SIZE2I;typedef struct _tagCOLOR4U{unsigned char b;unsigned char g;unsigned char r;unsigned char a;}COLOR4U;typedef struct _tagCOLOR4I{int b;int g;int r;int a;}COLOR4I;HDC _g_hDC;COLOR4U *_g_bitmap;COLOR4I _g_ftcolor;COLOR4I _g_bkcolor;SIZE2I _g_size={300,200};SIZE2I _g_oldsize={-100,-100};int _g_win_test=0;EXC WIN32GDI_API void CALL SetGraphicsDC(HDC shdc){_g_hDC=shdc;}EXC WIN32GDI_API void CALL InitGraph(int w,int h){if(w<200)w=200;if(h<180)h=180;_g_size.width=w;_g_size.height=h;if(_g_win_test==1){if(_g_size.width!=_g_oldsize.width||_g_size.height!=_g_oldsize.height){ _g_oldsize=_g_size;delete []_g_bitmap;_g_bitmap=new COLOR4U [_g_size.width*_g_size.height];}}if(_g_win_test==0){_g_oldsize=_g_size;_g_bitmap=new COLOR4U [_g_size.width*_g_size.height];_g_win_test=1;}}int TestNumber(int number){if(number>255) number=255;if(number<0) number=0;return number;}COLOR4I GetColor4i(int r,int g,int b,int a){COLOR4I cr={b,g,r,a};return cr;}EXC WIN32GDI_API void CALL SetColor(int r,int g,int b){r=TestNumber(r);g=TestNumber(g);b=TestNumber(b);_g_ftcolor=GetColor4i(r,g,b,0);}EXC WIN32GDI_API void CALL SetBackColor(int r,int g,int b){r=TestNumber(r);g=TestNumber(g);b=TestNumber(b);_g_bkcolor=GetColor4i(r,g,b,0);}EXC WIN32GDI_API void CALL Flush(){HBITMAP _cgl_bitmap=CreateBitmap(_g_size.width,_g_size.height,1,32,_g_bitmap);HBRUSH hb=CreatePatternBrush(_cgl_bitmap);SelectObject(_g_hDC,hb);Rectangle(_g_hDC,10,10,_g_size.width-25,_g_size.height-50);DeleteObject(hb);DeleteObject(_cgl_bitmap);}COLOR4U GetColor4u(COLOR4I ci){COLOR4U ti={ci.b,ci.g,ci.r,ci.a};return ti;}EXC WIN32GDI_API void CALL Clear(){int len,i;COLOR4U tm=GetColor4u(_g_bkcolor);len=_g_size.width*_g_size.height;for(i=0;i<len;i++){_g_bitmap[i]=tm;}}EXC WIN32GDI_API void CALL SetPixel2i(int x,int y){COLOR4U tm;tm=GetColor4u(_g_ftcolor);if(x>=0&&x<_g_size.width-1&&y>=0&&y<_g_size.height-1){int len=y*_g_size.width+x;_g_bitmap[len]=tm;}}EXC WIN32GDI_API void CALL Line2Di (int x1,int y1,int x2,int y2){int i,len;float dx,dy,x,y;x=(float)x1;y=(float)y1;if(abs(x2-x1)>=abs(y2-y1))len=abs(x2-x1);elselen=abs(y2-y1);SetPixel2i((int)x,(int)y);dx=(float)(x2-x1)/len;dy=(float)(y2-y1)/len;for(i=1;i<=len;i++){x+=dx;y+=dy;SetPixel2i((int)x,(int)y);}}5. 在Graph.def文件中编写Lib(*.dll)入口函数名字的源文件LIBRARY GraphEXPORTSSetGraphicsDCInitGraphSetColorSetBackColorFlushClearSetPixel2iLine2Di6. 编译动态链接库文件图5、成功编译Graph.dll7. 把生成的Graph.dll文件拷贝到C:\Windows\System中(Win7系统)8. 打开VB6:新建工程-标准EXE图6、VB工程源码屏幕截图9. 运行工程图7、VB工程执行结果屏幕截图至此就完成了从编写动态链接库到调用库的全过程。
dll文件生成方法

dll文件生成方法
DLL(动态链接库)文件的生成可以通过多种方式,其中一种简单的方法是通过 Microsoft Visual Studio 这样的集成开发环境(IDE)进行。
下面是详细的步骤:
1. 创建环境:首先,确保你已经安装了 Microsoft Visual Studio。
其他版本的 Visual Studio(如 Visual Studio 2022)也可以,但步骤大致相同。
2. 创建 DLL 项目:
打开 Visual Studio。
选择“新建项目”。
在项目模板中选择“DLL”。
输入 DLL 的名称,然后点击“确定”。
3. 编写 DLL 代码:在创建的项目中,你可以开始编写 DLL 的代码。
一个简单的 DLL 可能包含一个导出函数。
4. 编译 DLL:
在 Visual Studio 中,点击“生成”菜单,然后选择“生成解决方案”或直接按 F7 键。
5. 检查生成的 DLL:编译成功后,可以在项目文件夹的“Debug”或“Release”子文件夹下找到生成的 DLL 文件。
6. 测试 DLL:为了测试 DLL 是否正常工作,你可以创建一个新的Windows 应用程序项目,并在其中调用你的 DLL。
7. 分发 DLL:如果你想将 DLL 分发给其他人,只需将 DLL 文件和任何依赖项一起打包即可。
请注意,这只是生成 DLL 的其中一种方法。
还有其他工具和平台(如 Linux)可以使用,具体取决于你的需求和环境。
(动态链接库)DLL编写与使用方法

DLL的创建与调用1、DLL的概念DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。
这些可以直接拿来使用。
静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式。
静态链接库把最后的指令都包含在最终生成的EXE 文件中了;动态链接库不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
(2)静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
动态链接库的分类:Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
非MFC动态库不采用MFC 类库结构,其导出函数为标准的C接口,能被非MFC或MFC编写的应用程序所调用;MFC规则DLL 包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写的应用程序所调用。
2、创建一个DLL2.1 非MFC的DLL2.1.1声明导出函数:extern “C” __declspec(dllexport) int add(int a, int b);其中extern “C”为声明为C编译。
由于C++编译器在编译的时候会造成其函数名的该变,在其他应用程序中导致函数不可调用,而C编译器则不会在编译后改变其函数名。
这样如果用C编译的程序来调用该dll中的函数时,可能会造成找不到该函数。
__declspec(dllexport)表示该函数为DLL输出函数,即其他应用程序可以调用该函数从dll中声明输出函数有两种方式:(1)另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC++动态链接库(DLL)编程深入浅出1.概论先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。
在仓库的发展史上经历了“无库-静态链接库-动态链接库”的时代。
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。
但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL 文件。
静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
对动态链接库,我们还需建立如下概念:(1)DLL 的编制与具体的编程语言及编译器无关只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。
譬如Windows提供的系统DLL(其中包括了Windows的API),在任何开发环境中都能被调用,不在乎其是Visual Basic、Visual C++还是Delphi。
(2)动态链接库随处可见我们在Windows目录下的system32文件夹中会看到kernel32.dll、user32.dll和gdi32.dll,windows的大多数API都包含在这些DLL中。
kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。
一般的程序员都用过类似MessageBox的函数,其实它就包含在user32.dll这个动态链接库中。
由此可见DLL对我们来说其实并不陌生。
(3)VC动态链接库的分类Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL (MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
非MFC动态库不采用MFC类库结构,其导出函数为标准的C接口,能被非MFC或MFC 编写的应用程序所调用;MFC规则DLL 包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写的应用程序所调用。
由于本文篇幅较长,内容较多,势必需要先对阅读本文的有关事项进行说明,下面以问答形式给出。
问:本文主要讲解什么内容?答:本文详细介绍了DLL编程的方方面面,努力学完本文应可以对DLL有较全面的掌握,并能编写大多数DLL程序。
问:如何看本文?答:本文每一个主题的讲解都附带了源代码例程,可以随文下载(每个工程都经WINRAR压缩)。
所有这些例程都由笔者编写并在VC++6.0中调试通过。
当然看懂本文不是读者的最终目的,读者应亲自动手实践才能真正掌握DLL的奥妙。
问:学习本文需要什么样的基础知识?答:如果你掌握了C,并大致掌握了C++,了解一点MFC的知识,就可以轻松地看懂本文。
2.静态链接库对静态链接库的讲解不是本文的重点,但是在具体讲解DLL之前,通过一个静态链接库的例子可以快速地帮助我们建立“库”的概念。
图1 建立一个静态链接库如图1,在VC++6.0中new一个名称为libTest的static library工程(单击此处下载本工程附件),并新建lib.h和lib.cpp两个文件,lib.h和lib.cpp的源代码如下://文件:lib.h#ifndef LIB_H#define LIB_Hextern "C" int add(int x,int y);//声明为C编译、连接方式的外部函数#endif//文件:lib.cpp#include "lib.h"int add(int x,int y){return x + y;编译这个工程就得到了一个.lib文件,这个文件就是一个函数库,它提供了add的功能。
将头文件和.lib文件提交给用户后,用户就可以直接使用其中的add函数了。
标准Turbo C2.0中的C库函数(我们用来的scanf、printf、memcpy、strcpy等)就来自这种静态库。
下面来看看怎么使用这个库,在libTest工程所在的工作区内new一个libCall工程。
libCall工程仅包含一个main.cpp文件,它演示了静态链接库的调用方法,其源代码如下:#include <stdio.h>#include "..\lib.h"#pragma comment( lib, "..\\debug\\libTest.lib" ) //指定与静态库一起连接int main(int argc, char* argv[]){printf( "2 + 3 = %d", add( 2, 3 ) );}静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。
代码中#pragma comment( lib , "..\\debug\\libTest.lib" )的意思是指本文件生成的.obj文件应与libTest.lib一起连接。
如果不用#pragma comment指定,则可以直接在VC++中设置,如图2,依次选择tools、options、directories、library files菜单或选项,填入库文件路径。
图2中加红圈的部分为我们添加的libTest.lib文件的路径。
图2 在VC中设置库文件路径这个静态链接库的例子至少让我们明白了库函数是怎么回事,它们是哪来的。
我们现在有下列模糊认识了:(1)库不是个怪物,编写库的程序和编写一般的程序区别不大,只是库不能单独执行;(2)库提供一些可以给别的程序调用的东东,别的程序要调用它必须以某种方式指明它要调用之。
以上从静态链接库分析而得到的对库的懵懂概念可以直接引申到动态链接库中,动态链接库与静态链接库在编写和调用上的不同体现在库的外部接口定义及调用方式略有差异。
3.库的调试与查看在具体进入各类DLL的详细阐述之前,有必要对库文件的调试与查看方法进行一下介绍,因为从下一节开始我们将面对大量的例子工程。
由于库文件不能单独执行,因而在按下F5(开始debug模式执行)或CTRL+F5(运行)执行时,其弹出如图3所示的对话框,要求用户输入可执行文件的路径来启动库函数的执行。
这个时候我们输入要调用该库的EXE文件的路径就可以对库进行调试了,其调试技巧与一般应用工程的调试一样。
图3 库的调试与“运行”通常有比上述做法更好的调试途径,那就是将库工程和应用工程(调用库的工程)放置在同一VC工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下F11,这样就单步进入了库中的函数。
第2节中的libTest和libCall工程就放在了同一工作区,其工程结构如图4所示。
图4把库工程和调用库的工程放入同一工作区进行调试上述调试方法对静态链接库和动态链接库而言是一致的。
所以本文提供下载的所有源代码中都包含了库工程和调用库的工程,这二者都被包含在一个工作区内,这是笔者提供这种打包下载的用意所在。
动态链接库中的导出接口可以使用Visual C++的Depends工具进行查看,让我们用Depends打开系统目录中的user32.dll,看到了吧?红圈内的就是几个版本的MessageBox了!原来它真的在这里啊,原来它就在这里啊!图5用Depends查看DLL当然Depends工具也可以显示DLL的层次结构,若用它打开一个可执行文件则可以看出这个可执行文件调用了哪些DLL。
好,让我们正式进入动态链接库的世界,先来看看最一般的DLL,即非MFC DLL。
上节给大家介绍了静态链接库与库的调试与查看,本节主要介绍非MFC DLL。
4.非MFC DLL4.1一个简单的DLL第2节给出了以静态链接库方式提供add函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的add函数。
如图6,在VC++中new一个Win32 Dynamic-Link Library工程dllTest(单击此处下载本工程附件)。
注意不要选择MFC AppWizard(dll),因为用MFC AppWizard(dll)建立的将是第5、6节要讲述的MFC 动态链接库。
图6 建立一个非MFC DLL在建立的工程中添加lib.h及lib.cpp文件,源代码如下:/* 文件名:lib.h*/#ifndef LIB_H#define LIB_Hextern "C" int __declspec(dllexport)add(int x, int y);#endif/* 文件名:lib.cpp*/#include "lib.h"int add(int x, int y){return x + y;}与第2节对静态链接库的调用相似,我们也建立一个与DLL工程处于同一工作区的应用工程dllCall,它调用DLL中的函数add,其源代码如下:#include <stdio.h>#include <windows.h>typedef int(*lpAddFun)(int, int); //宏定义函数指针类型int main(int argc, char *argv[]){HINSTANCE hDll; //DLL句柄lpAddFun addFun; //函数指针hDll = LoadLibrary("..\\Debug\\dllTest.dll");if (hDll != NULL){addFun = (lpAddFun)GetProcAddress(hDll, "add");if (addFun != NULL){int result = addFun(2, 3);printf("%d", result);}FreeLibrary(hDll);}return 0;}分析上述代码,dllTest工程中的lib.cpp文件与第2节静态链接库版本完全相同,不同在于lib.h对函数add的声明前面添加了__declspec(dllexport)语句。
这个语句的含义是声明函数add为DLL的导出函数。
DLL内的函数分为两种:(1)DLL导出函数,可供应用程序调用;(2) DLL内部函数,只能在DLL程序使用,应用程序无法调用它们。