动态链接库编程

合集下载

动态链接库(DLL)编程深入浅出(3)精品文档11页

动态链接库(DLL)编程深入浅出(3)精品文档11页

第4节我们对非MFC DLL进行了介绍,这一节将详细地讲述MFC规则DLL的创建与使用技巧。

另外,自从本文开始连载后,收到了一些读者的e-mail。

有的读者提出了一些问题,笔者将在本文的最后一次连载中选取其中的典型问题进行解答。

由于时间的关系,对于读者朋友的来信,笔者暂时不能一一回复,还望海涵!由于笔者的水平有限,文中难免有错误和纰漏,也热诚欢迎读者朋友不吝指正!MFC规则DLL的概念体现在两方面:(1)它是MFC的“是MFC的”意味着可以在这种DLL的内部使用MFC;(2)它是规则的“是规则的”意味着它不同于MFC扩展DLL,在MFC规则DLL的内部虽然可以使用MFC,但是其与应用程序的接口不能是MFC。

而MFC扩展DLL与应用程序的接口可以是MFC,可以从MFC扩展DLL中导出一个MFC类的派生类。

Regular DLL能够被所有支持DLL技术的语言所编写的应用程序调用,当然也包括使用MFC的应用程序。

在这种动态连接库中,包含一个从CWinApp继承下来的类,DllMain 函数则由MFC自动提供。

Regular DLL分为两类:(1)静态链接到MFC 的规则DLL静态链接到MFC的规则DLL与MFC库(包括MFC扩展DLL)静态链接,将MFC 库的代码直接生成在.dll文件中。

在调用这种DLL的接口时,MFC使用DLL的资源。

因此,在静态链接到MFC 的规则DLL中不需要进行模块状态的切换。

使用这种方法生成的规则DLL其程序较大,也可能包含重复的代码。

(2)动态链接到MFC 的规则DLL动态链接到MFC 的规则DLL 可以和使用它的可执行文件同时动态链接到MFC DLL 和任何MFC扩展DLL。

在使用了MFC共享库的时候,默认情况下,MFC使用主应用程序的资源句柄来加载资源模板。

这样,当DLL和应用程序中存在相同ID的资源时(即所谓的资源重复问题),系统可能不能获得正确的资源。

因此,对于共享MFC DLL的规则DLL,我们必须进行模块切换以使得MFC能够找到正确的资源模板。

C#中创建和使用动态链接库

C#中创建和使用动态链接库

C#中创建和使⽤动态链接库动态链接库英⽂为DLL,是Dynamic Link Library 的缩写形式,DLL是⼀个包含可由多个程序同时使⽤的代码和数据的库,它有助于共享数据和资源。

(⼀)创建动态链接库1)新建⼀个类库2)编写该类库例如:1: using System;2: using System.Collections.Generic;3: using System.Linq;4: using System.Text;5:6: namespace DllTest7: {8: public class MyClass9: {10: public void ShowMessage()11: {12: Console.WriteLine("你已成功调⽤了动态链接!");13: Console.ReadLine();14: }15: }16: }3)⽣成动态链接库(⼆)使⽤动态链接库1)添加引⽤右击项⽬-添加引⽤-浏览找到本地的dll⽂件2)using 该dll⽂件⾥⾯代码的名称空间例如:1: using System;2: using System.Collections.Generic;3: using System.Linq;4: using System.Text;5:6: //using 要引⽤的dll⽂件的命名空间7: using DllTest;8:9: namespace DllExample10: {11: class Program12: {13: static void Main(string[] args)14: {15: DllTest.MyClass myTest = new DllTest.MyClass();16: myTest.ShowMessage();17: }18: }19: }。

VC 动态链接库(DLL)编程

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)。

动态链接库(DLL)应用编程

动态链接库(DLL)应用编程

(3)用exports语句声明供其它应用程序 调用的函数和过程名
函数或过程定义好后,为了能够被其它应用程序调用, 还 必 须 用Exports 子句把 函数名列 出 .本 例使 用的 Exports语句如下: exports Max,Min; Exports语句的格式与功能如下: exports entry1,entry2,……,entryn;
【例10-2】 编写一个应用程序用来调用例 10-1所建立的动态链接库中的Max和Min函数, 要求使用隐式调用.程序的设计界面如图10-4 所示,函数的运行界面如图10-5所示.程序运 10-5 行时输入三个数到三个编辑框中,然后按 【求最大值】按钮,将会求出三个数的最大 值并显示在第四个文本框中,如果按【求最 小值】按钮,将会求出三个数的最小值并显 示在第四个文本框中.
2.静态链接和动态链接
(1)静态链接
传统的库函数是通过静态链接链到应用程序中的. 这些库函数可能来自编程语言提供的标准库,也可能 是由操作系统提供的API.
(2)动态链接
动态链接是指在把应用程序的目标代码链接成 EXE文件时并没有将函数库中的函数复制到应用程序 的可执行文件中,而是在程序运行时动态地加载所需 的函数.
图10-6 设计界面
为完成本题的功能,应经历以下步骤.
(1)设计窗体. 新建一个应用程序,按图10-6所示给Form1添加组 件对象. (2)编写输出函数或过程,实例化窗体. (3)修改工程文件,使之能生成DLL文件
窗体单元编制完成之后,可把应用程序项目转换为DLL.首 先执行【Proiect】→【View】 Source】命令来打开.dpr项目 文件,并在代码编辑器中做如下修改: ①把program改为Library; ②从Uses指令中删除Forms;

第4章动态链接库(DLLs)编程

第4章动态链接库(DLLs)编程

(2) 输出函数还应该被声明为stdcall, 以使用标准的Win32参数传递技术来代替 优化的register参数传递技术。
(3) DLL的参数类型应是缺省的Windows 类型,使得该DLL能应用于其它开发环境 中。
(4) DLL可以使用全局数据,该数据将不 会通过调用应用程序来共享。每当应用 程序装载DLL时,它在自己的地址空间中 存储着DLL的全局数据。
程或函数的输出名。如:

exports
InStr name ’MyInstr’;
其它应用程序将用新名字(MyInstr)调 用该过程或函数。如果仍利用原来的名 字(InStr),则在程序执行到引用点时 会引发一个系统错误。
2.Index
Index指示为过程或函数分配一个顺 序号。如果不使用Index指示,则由编译 器按顺序进行分配。
在Win32中,因为DLL映射于应用程 序的地址空间中,所以DLL的任何内存分 配或建立的任何全局数据都驻留在主进 程的地址空间中。
4.1.5 DLL编写规则
由外部程序调用的DLL函数或过程必 须遵照以下这些规则:
(1) 它必须列在DLL的exports句子中。 这使子例程在DLL外部就可以看到。
(1) 如果不同的程序使用相同的DLL,只 需将DLL在内存中装载一次,这样节省了 系统内存。
(2) 可以提供DLL的不同版本,代替当前 的DLL。如果DLL中的子例程有相同的参 数,可以用新版本的DLL运行程序,而不 需要重新编译它。
这些通用的优点可以应用于多种情 况中。如果我们有一些复杂算法,或一 些复杂窗体,它们是多个应用程序所需 要的,可以将它们存储在DLL中。
这样做,在同时运行多个使用该DLL 的程序时,可以减小执行文件的规模, 并节省一些内存。

windows动态链接库编程详解

windows动态链接库编程详解

Windows Dynamic-Link Library1.概论先来阐述一下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)。

C语言动态链接库编程

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工程执行结果屏幕截图至此就完成了从编写动态链接库到调用库的全过程。

Windows编程技术13-动态链接库

Windows编程技术13-动态链接库
DLL成功加载,使用GetProcAddress()得到DLL中函数的指针。 GetProcAddress(HMODULE hModule,LPCSTR lpProcName);
释放DLL 使用完DLL后,应使用FreeLibrary()函数释放DLL。其函数原形为: BOOL FreeLibrary(HMODULE hModule); BOOL AfxFreeLibrary(HINSTANCE hInstLib );
显式加载 加载DLL 在动态加载DLL时,首先需要将DLL模块映射到进程的内存空间。该功 能可以由Windows API函数LoadLibrary()或MFC的全局函数 AfxLoadLibrary()实现。以下是LoadLibrary()函数原形。 HMODULE LoadLibrary(LPCTSTR lpFileName); HINSTANCE AfxLoadLibrary(LPCTSTR lpFileName); 取得函数指针

生成DLL
将以上程序进行编译链接,可以生成两个重要文件: “MyDll.lib”将在隐式链接时使用。 “MyDll.dll”即为生成的动态链接库,它包含函数代码,在程序执行 时链接使用。
5
创建标准MFC动态库

新建标准MFC动态库项目 添加函数

在“应用程序设置/应用程序类型”的选项中选MFC DLL类型,然后“ 完成”
Windows编程技术
动态链接库
1
概述
动态链接是在程序链接并最终生成可执行文件时,保留程 序到函数库的调用接口。当应用程序运行时,它需要通过其前 面的接口找到对应的函数库文件,当执行函数功能时,转到函 数库中的对应函数执行。 两种类型的DLL Win32 DLL MFC DLL 动态库的加载方式 隐式加载 显式加载。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

VC++动态链接库(DLL)编程――理解库作者:宋宝华e-mail:21cnbao@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静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。

代码中#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。

4动态库4.1一个简单的dll第2节给出了以静态链接库方式提供add函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的add函数。

如图6,在VC++中new一个Win32Dynamic-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);}return0;}分析上述代码,dllTest工程中的lib.cpp文件与第2节静态链接库版本完全相同,不同在于lib.h对函数add的声明前面添加了__declspec(dllexport)语句。

这个语句的含义是声明函数add为DLL的导出函数。

DLL内的函数分为两种:(1)DLL导出函数,可供应用程序调用;(2)DLL内部函数,只能在DLL程序使用,应用程序无法调用它们。

而应用程序对本DLL的调用和对第2节静态链接库的调用却有较大差异,下面我们来逐一分析。

首先,语句typedef int(*lpAddFun)(int,int)定义了一个与add函数接受参数类型和返回值均相同的函数指针类型。

随后,在main函数中定义了lpAddFun的实例addFun;其次,在函数main中定义了一个DLL HINSTANCE句柄实例hDll,通过Win32 Api函数LoadLibrary动态加载了DLL模块并将DLL模块句柄赋给了hDll;再次,在函数main中通过Win32Api函数GetProcAddress得到了所加载DLL模块中函数add的地址并赋给了addFun。

经由函数指针addFun进行了对DLL 中add函数的调用;最后,应用工程使用完DLL后,在函数main中通过Win32Api函数FreeLibrary释放了已经加载的DLL模块。

相关文档
最新文档