VC++ MFC DLL动态链接库编写详解
- 格式:doc
- 大小:35.50 KB
- 文档页数:7
第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能够找到正确的资源模板。
如何用VC编写DLL动态链接库文件作者: falcon 发表日期: 2006-04-24 14:51引言前不久刚学会了如何用VB编写DLL动态链接库,但是用vb编写动态链接库比较麻烦些。
下面我们再学习一下如何用vc编写dll动态链接库,并且通过vc或者vb调用正文这里主要介绍两个东东第一:用vc编写动态链接库,用vc调用第二:用vb编写动态链接库,用vb调用一、用vc编写动态链接库,用vc调用1、创建DLL文件,命名为FIRSTDLL1)打开visual c++ 6.0通过new创建一个win30 Dynamic-link Libary的工程,命名为FIRSTDLL2)接着选择最后一个选项,让系统帮我们创建一些必要的文件3)把FIRSTDLL.cpp用下面的代码覆盖Code:[Ctrl+A Select All]4)接着我们在FIRSTDLL.h头文件里头用下面的代码覆盖Code:[Ctrl+A Select All]5)好拉,我们现在可以编译FIRSTDLL.cpp文件拉,到debug目录下看看,是不是已经生成拉我们需要的FIRSTDLL.dll拉2、通过vb编写一个函数来调用该DLL,该函数为USEFIRSTDLL1)同样通过new创建一个工程,该工程为win30 application,命名USEFIRSTDLL2)在USEFIRSTDLL.cpp文件中用如下代码覆盖Code:[Ctrl+A Select All]好拉,到这里第一部分介绍完拉下面介绍第二部分二、用vc编写动态链接库,用vb调用在介绍这个之前必须声明的是(引用自下面的参考资料)一个DLL中的函数要想被VB调用,必须满足两个条件:一是调用方式为stdcall,另一个是必须是export的。
要做到第一条,只须在函数声明前加上__stdcall关键字。
如:short __stdcall sample(short nLen, short *buffer)要做到第二条,需要在*.def文件中加上如下的几行:EXPORTSsample @1这里的sample是你要在VB中调用的函数名,@1表示该函数在DLL中的编号,每个函数都不一样。
C语⾔创建动态dll和调⽤dll(visualstudio2013环境下)第⼀部分:创建动态dll库。
1、打开visual studio 创建⼀个控制台应⽤程序。
2、选择DLL,空项⽬。
3、点击源⽂件,创建⼀个main.c⽂件4、在main.c中写⼊⼀个简单的函数,内容如下:__declspec(dllexport)int mymax(int a,int b){return a + b;}5、编译⽣成。
6、在项⽬的⽬录有dll和lib两个⽣成好的⽂件。
第⼆部分:在新建项⽬中使⽤dll。
7、新建⼀个c的控制台应⽤程序UseDll,把Dll.dll放⼊Debug⽬录下。
8、把Dll.lib放⼊UserDll⽬录下。
9、在UseDll项⽬中新建⼀个源⽂件use.c,代码如下:#include<stdio.h>#pragma comment(lib,"Dll.lib")int mymax(int a,int b);int main(){printf("调⽤动态dll函数的结果:%d",mymax(5,6));getchar();return 0;}10、运⾏结果如下PS:vs2013调试程序时出现“计算机丢失.dll⽂件”在VS环境下能够编译成功,但是在运⾏.exe⽂件时,出现“计算机丢失xxx.dll⽂件”的提⽰的解决⽅式。
发⽣这种问题的根本原因在于环境变量的设置上,计算机只会在path下包含的⽬录⾥去寻找程序所要运⾏的.dll⽂件,若我们所要使⽤到的.dll⽂件没有包含在环境变量path中,则会发⽣错误:计算机丢失xxx.dll⽂件。
⼯具/原料1. VS2013或者其他版本2. VTK库或者其他库⽅法/步骤这⾥以丢失vtkIOPLY-7.0-gd.dll⽂件为例(主要是关于PCL1.8.0),找到VTK的安装⽬录下的bin⽂件夹(包含vtkIOPLY-7.0-gd.dll),我的bin⽂件夹是在C:\Program Files (x86)\PCL1.8.0\3rdParty\VTK\bin将上述⽬录添加到环境变量Path中,如下图所⽰重新开启项⽬,重新⽣成解决⽅案,则问题就会解决注意事项这⾥不仅仅是针对vtkIOPLY-7.0-gd.dll⽂件,任何丢失.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可以采用两种方式:一种是隐式链接,另一种是显式链接。
VC 动态链接库(DLL)编程深入浅出4这是《VC++动态链接库(DLL)编程深入浅出》的第四部分,阅读本文前,请先阅读前三部分:(一)、(二)、(三)。
MFC扩展DLL的内涵为MFC的扩展,用户使用MFC 扩展DLL就像使用MFC本身的DLL一样。
除了可以在MFC扩展DLL的内部使用MFC以外,MFC扩展DLL与应用程序的接口部分也可以是MFC。
我们一般使用MFC扩展DLL来包含一些MFC的增强功能,譬如扩展MFC的CStatic、 CButton等类使之具备更强大的能力。
使用Visual C++向导生产MFC扩展DLL时,MFC向导会自动增加DLL的入口函数DllMain:extern \DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {// Remove this if you use lpReserved UNREFERENCED_PARAMETER(lpReserved);if (dwReason == DLL_PROCESS_ATTACH) {TRACE0(\// Extension DLL one-time initializationif (!AfxInitExtensionModule(MfcexpenddllDLL, hInstance)) return 0;// Insert this DLL into the resource chain// NOTE: If this Extension DLL is being implicitly linked to by // an MFC Regular DLL (such as an ActiveX Control) // instead of an MFC application, then you will want to // remove this line from DllMain and put it in a separate // function exported from this Extension DLL. The Regular DLL // that uses this Extension DLL should then explicitly call that // function to initialize this Extension DLL. Otherwise, // the CDynLinkLibrary object will not be attached to the // Regular DLL's resource chain, and serious problems will // result.new CDynLinkLibrary(MfcexpenddllDLL); }else if (dwReason == DLL_PROCESS_DETACH) {TRACE0(\ // Terminate the library before destructors are called AfxTermExtensionModule(MfcexpenddllDLL); }return 1; // ok }上述代码完成MFC扩展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文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
如何用VC创建及调用DLL使用Visual C++(VC++)创建和调用动态链接库(DLL)可以提供一种模块化的方式来组织和重用代码。
本文将介绍如何使用VC++创建DLL,并在另一个VC++项目中调用该DLL。
创建DLL以下是使用VC++创建DLL的步骤:1.打开VC++,在“文件”菜单中选择“新建”->“项目”。
2. 在“新建项目”对话框中,选择“Win32控制台应用程序”。
点击“下一步”。
3.输入项目名称,并选择项目位置,点击“下一步”。
4.在“应用程序类型”对话框中,选择“DLL”并取消勾选“预编译头”。
点击“下一步”。
5.在“进入代码”对话框中,选择“空项目”。
点击“完成”。
6. 创建一个新的源文件,例如“MyDLL.cpp”。
7. 在“MyDLL.cpp”中,编写所需的函数并导出。
例如:```C++#include <Windows.h>// 导出的函数需要使用__declspec(dllexport)修饰extern "C" __declspec(dllexport) int AddNumbers(int a, int b) return a + b;```8. 在项目属性中,选择“链接器”->“高级”,将“入口点”设置为“DllMain”。
9.在“生成”菜单中选择“生成解决方案”,以生成DLL文件。
以下是在VC++项目中调用DLL的步骤:1.打开VC++,在“文件”菜单中选择“新建”->“项目”。
2. 在“新建项目”对话框中,选择“Win32控制台应用程序”。
点击“下一步”。
3.输入项目名称,并选择项目位置,点击“下一步”。
4.在“应用程序类型”对话框中,选择“控制台应用程序”并取消勾选“预编译头”。
点击“下一步”。
5.在“附加选项”对话框中,勾选“空项目”。
点击“完成”。
6.将之前生成的DLL文件复制到新项目的文件夹中。
7.在项目属性中,选择“C/C++”->“常规”,将“附加包含目录”设置为包含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)。
《学习如何使用C语言编写动态链接库》此文首先介绍如何使用C语言编写动态链接库(DLL)。
通常,我们使用外部应用程序来调用DLL中的函数,以提供丰富的功能,而不需要重新编写相同的代码。
DLL文件可以保存各种可执行代码,如函数,模块,等等,以实现不同的任务。
就像在其他编程语言中一样,开发人员也可以在C语言中创建DLL。
下面将介绍如何在Visual C ++中使用Visual Studio创建DLL。
首先,运行Visual Studio并选择“新建项目”。
然后,在新建项目窗口中,选择“模块库”类型,并输入所需的项目名称。
接下来,把选定的语言设置为C,并指定模块库类型为“动态链接库”。
现在,可以继续定义模块库文件的详细信息,如应用程序名称,文件名等。
最后,选择“确定”以创建新项目。
现在,Visual Studio会显示一个新创建的工作空间,其中包含两个文件。
第一个文件是source.c,其中包含主函数的代码,可帮助外部应用程序调用该函数。
第二个文件是dllmain.c,其中包含所有关于DLL的函数调用,以及DLL如何实现功能的相关信息。
在dllmain.c文件中,还能够定义函数原型,以实现不同的任务,如数学运算,文本处理,图像处理,网络连接等等。
解决方案导航器中也有一些可用的操作,如建立新的文件,编译/连接文件,调整属性,预编译等。
Visual Studio也提供了一些编程工具,如断点调试,查看堆栈跟踪,查看变量值,查看执行代码等。
这些工具可以帮助开发人员轻松调试代码,以获得最佳性能。
此外,Visual Studio提供了一些功能,使模块库链接成功。
例如,它可以自动生成lib文件,并将其链接到外部应用程序,以便调用函数。
如果使用Visual Studio编写了一些可重复使用的代码,也可以创建一个可重用模块库,以便在多个应用程序中使用。
总之,使用C语言编写动态链接库(DLL)非常容易,而使用Visual Studio来实现这一目标可以提供更多的功能和可用性。
深入浅出VisualC++动态链接库(DLL)编程(第一章)vs2010篇我们的群:关于这篇文章第一章:VC++动态链接库编程之基础慨念1.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文件的方法步骤,一起来学习一下,并不是很难的,相信聪明的你一看就会。
一.Win32动态链接库1.制作的步骤:(1)新建WIN32 Dynamic-link Library工程,工程名为MyDll,选择A simple DLL project类型。
(2)MyDll.h的内容如下:(3)MyDll.cpp的内容如下:2.使用方法:(1).隐式调用法:将MyDll.lib和MyDll.h拷贝到需要应用该DLL 的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行:(2).显示调用法:将MyDll.lib和MyDll.h拷贝到需要应用该DLL 的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中包含头文件,如:同时还需要在Project->Setting->Link->Object/library modules的框中增加MyDll.lib这个库。
二.MFC动态链接库1.制作的步骤:(1)新建MFC AppWizard(dll)工程,工程名为MFCDll,选择Regular DLL using shared MFC DLL类型。
(2)在生成的MFCDll.cpp文件后面增加下面几行:(3)在生成的MFCDll.def文件后面增加如下:(4)编译后会产生两个文件MFCDll.lib,MFCDll.dll2.使用方法(1)隐式调用法:将MFCDll.lib拷贝到需要应用该DLL的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行://注意这里没有在MFCDll.h中声明函数,所以不能直接包含MFCDll.h来声明函数。
//当然如果你的DLL中有很多函数,那可以另外写个MFCDll.h,包含所有的函数声明,然后直接将头文件包含进去(2)显示调用法:与Win32的调用方法一样,不需要#pragma comment(lib,"MFCDll");,但是需要在Project->Setting->Link->Object/library modules的框中增加MFCDll.lib这个库。
VC++动态链接库(DLL)编程深入浅出(一)1.概论先来阐述一下D LL(Dynamic Linkabl e Library)的概念,你可以简单的把DLL 看成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。
在仓库的发展史上经历了“无库-静态链接库-动态链接库”的时代。
[被屏蔽广告] 静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都被直接包含在最终生成的 EXE 文件中了。
但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。
静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
对动态链接库,我们还需建立如下概念:(1)DLL 的编制与具体的编程语言及编译器无关只要遵循约定的DLL 接口规范和调用方式,用各种语言编写的 DLL 都可以相互调用。
譬如 Windows提供的系统 DLL(其中包括了 Windows的 API),在任何开发环境中都能被调用,不在乎其是 VisualBasic、VisualC++还是 Delphi。
(2)动态链接库随处可见我们在 Windows目录下的 system32 文件夹中会看到kernel32.dll、user32.dll 和 gdi32.dll,windows的大多数 API 都包含在这些DLL 中。
kernel32.dll 中的函数主要处理内存管理和进程调度;user32.dll 中的函数主要控制用户界面;gdi32.dll 中的函数则负责图形方面的操作。
一般的程序员都用过类似 Message Box 的函数,其实它就包含在user32.dll这个动态链接库中。
中定义和使用MFCDLL基础教程基础实例VC++.NET中定义和使用MFC DLL什么是DLL?DLL指的是动态链接库(Dynamic Link Library),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库。
DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。
在下面我们将通过一个具体的例子来说明如何利用定义一个DLL文件,并且在的应用程序中调用,这个例子的主要功能是通过DLL获取系统的机器名、操作系统类型和IP地址。
在中定义DLL文件选择菜单项,选择文件->新建->项目,在弹出的新建项目的对话框中,选择项目类型为Visual C++ 项目,类别为MFC的工程,在右边的模板中,选择MFC DLL模板,给项目取名为T estDLL,选择好项目的位置,按确定健,进入应用程序设置。
在应用程序设置中,我们可以看到,有三种DLL类型,它们依次对应着三类DLL。
静态DLL与共享DLL的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的共享DLL 所有输出的函数应该以如下语句开始(用于正确切换MFC模块状态):AFX_MANAGE_STATE(AfxGetStaticModuleState( )) 扩展DLL用来建立MFC的派生类,只被用MFC类库所编写的应用程序调用。
常规DLL(包括静态与动态)的一个特点是在源文件里有一个继承CWinApp的类(从CWinApp派生,但没有消息循环),被导出的函数是C++类或者C++成员函数,调用常规DLL的应用程序不必一定是MFC应用程序。
扩展DLL和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化。
C++编写DLL动态链接库的步骤与实现⽅法本⽂实例讲述了C++编写DLL动态链接库的步骤与实现⽅法。
分享给⼤家供⼤家参考,具体如下:在写C++程序时,时常需要将⼀个class写成DLL,供客户端程序调⽤。
这样的DLL可以导出整个class,也可以导出这个class的某个⽅法。
⼀、导出整个class⽅法很简单,只需要在类的头⽂件中class和类名之间加上_declspec(dllexport),同时在另外⼀份提供给客户端调⽤程序使⽤的类的头⽂件中class和类名之间加上_declspec(dllimport)。
为了能让客户端程序和DLL程序公⽤该类的⼀份头⽂件,通常在类的头⽂件中使⽤宏和预编译指令来处理。
如下DLLTest.h:#ifdef DLL_TEST_API#else#define DLL_TEST_API _declspec(dllimport)#endifClass DLL_TEST_API CDLLTest{Public:CDLLTest();~CDLLTest();int Add(int a, int b);};DLLTest.cpp如下:#define DLL_TEST_API _declspec(dllexport)#include "DLLTest.h"这样,在DLL编译时DLL_TEST_API被定义为_declspec(dllexport),⽽且客户端程序编译时它被定义为_declspec(dllimport)。
⼆、导出这个类的某个或者某⼏个⽅法这时,需要将_declspec(dllexport)放到成员函数名前,如DLLTest.h:#ifdef DLL_TEST_API#else#define DLL_TEST_API _declspec(dllimport)#endifClass CDLLTest{Public:CDLLTest(); ~CDLLTest();int DLL_TEST_API Add(int a, int b);};但是,如果仅仅是这样的话,当客户端程序#include这个头⽂件后,定义DLLTest这个类的⼀个对象后(静态⽅式链接DLL),客户端程序⽆法链接通过,会提⽰构造函数和析构函数⽆法解析,此时,需要将构造函数和析构函数前也加上DLL_TEST_API宏即可。
VC++ 6.0如何创建与调用动态链接库1.静态链接库与动态链接库区别:静态链接库:lib中的指令被直接包含在最终生成的EXE文件中。
动态链接库:dll不必被包含在最终的EXE中,EXE文件执行时可以动态地引用和卸载DLL文件。
同时,静态链接库中不能再包含其他的动态链接库或静态库,而动态链接库中可以包含其他的动态或静态库。
2.VC++支持的DLL:DLL的编制与具体的编程语言及编译器无关,动态链接库随处可见,VC++支持三种DLL:非MFC动态库、MFC规则DLL和MFC扩展DLL。
DLL导出函数(或变量、类)可供应用程序调用;DLL内部函数只能在DLL程序内使用,应用程序无法调用它们。
3.导出函数的声明方式:一种在函数声明类型和函数名之间加上“_declspec(dllexport)”。
另外一种采用模块定义(.def)文件声明,需要在库工程中添加模块文件,格式如下:LIBRARY 库工程名称EXPORTS 导出函数名4.DLL的调用方式:一种静态调用,由编译系统完成对DLL的加载和应用程序结束时DLL的卸载。
另外一种动态调用,由编程者用API函数加载和卸载DLL(DLL加载—DLL函数地址获取—DLL释放)方式。
5.所有库工程编译时必须Release方式:Build—set active configuration—选择库工程的release方式6.示例:一、函数----创建动态链接库(MFC规则DLL)1. New--projects--MFC AppWizard(dll)--Regular DLL using shared MFC DLL //取名为MFC_dll2. def文件中添加:函数名(Add_new)3. h文件中添加:外部函数声明//求和函数,函数名为Add_newextern "C" __declspec(dllexport) int __stdcall Add_new(int a,int b);4. cpp文件中添加:外部函数实现extern "C" __declspec(dllexport) int __stdcall Add_new(int a,int b){return a+b;}5. build--set active configuration--win32 release--ok6. 生成7. 根目录下release文件夹中dll,lib与根目录下h文件即为所需二、函数----调用动态链接库(把MFC_dll.dll和MFC_dll.lib拷到工程所在目录)//静态调用(.h可以写到.cpp文件中)1. new--projects--win32 console application--an empty project2. 添加h文件:(test.h)#pragma comment(lib,"MFC_dll.lib") //告诉编译器DLL相对应的lib文件所在路径和文件名extern "C" _declspec(dllimport) int _stdcall Add_new(int a,int b);//声明导入函数3. 添加cpp文件:(main.cpp)#include "test.h"int main(){cout<<Add_new(10,3);return 0;}//动态调用#include <stdio.h>#include <windows.h>typedef int (* lpAddFun)(int ,int);//定义一个与Add_new函数接受参数类型和返回值均相同的函数指针类型int main(){HINSTANCE hDll;//句柄lpAddFun addFun;//函数指针hDll=LoadLibrary("dllTest.dll");//动态加载DLL模块句柄if(hDll){addFun=(lpAddFun) GetProcAddress(hDll,"Add_new");//得到所加载DLL模块中函数的地址if(addFun){int result=addFun(2,3);printf("%d",result); } FreeLibrary(hDll);//释放已经加载的DLL模块}return 0;}三、变量----创建动态链接库(非MFC DLL)1. new---projects---win32 dynamic-link library----an empty project(Sample)2. 添加sample.h#ifndef SAMPLE_H#define SAMPLE_Hextern int dllGlobalVar;#endif3. 添加 sample.cpp#include "sample.h"#include <windows.h>int dllGlobalVar;bool APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)//windows在加载DLL时,需要一个入口函数,就如同控制台或DOS程序需要main函数、win32程序需要winmain函数一样。
VC++ MFC DLL动态链接库编写详解(2008-07-10 17:38:40)标签:it分类:com技术然能用DLL实现的功能都可以用COM来替代,但DLL的优点确实不少,它更容易创建。
本文将讨论如何利用VC MFC来创建不同类型的DLL,以及如何使用他们。
一、DLL的不同类型使用VC++可以生成两种类型的DLL:MFC扩展DLL和常规DLL。
常规DLL有可以分为动态连接和静态连接。
Visual C++还可以生成WIN32 DLL,但不是这里讨论的主要对象。
1、MFC扩展DLL每个DLL都有某种类型的接口:变量、指针、函数、客户程序访问的类。
它们的作用是让客户程序使用DLL,MFC扩展DLL可以有C++的接口。
也就是它可以导出C++类给客户端。
导出的函数可以使用C++/MFC数据类型做参数或返回值,导出一个类时客户端能创建类对象或者派生这个类。
同时,在DLL中也可以使用DLL和MFC。
Visual C++使用的MFC类库也是保存在一个DLL中,MFC扩展DLL动态连接到MFC代码库的DLL,客户程序也必须要动态连接到MFC代码库的DLL。
(这里谈到的两个DLL,一个是我们自己编写的DLL,一个装MFC类库的DLL)现在MFC代码库的DLL也存在多个版本,客户程序和扩展DLL都必须使用相同版本的MFC代码DLL。
所以为了让MFC扩展DLL能很好的工作,扩展DLL和客户程序都必须动态连接到MFC代码库DLL。
而这个DLL必须在客户程序运行的计算机上。
2、常规DLL使用MFC扩展DLL的一个问题就是DLL仅能和MFC客户程序一起工作,如果需要一个使用更广泛的DLL,最好采用常规DLL,因为它不受MFC的某些限制。
常规DLL也有缺点:它不能和客户程序发送指针或MFC派生类和对象的引用。
一句话就是常规DLL和客户程序的接口不能使用MFC,但在DLL和客户程序的内部还是可以使用MFC。
当在常规DLL的内部使用MFC代码库的DLL时,可以是动态连接/静态连接。
如果是动态连接,也就是常规DLL需要的MFC代码没有构建到DLL中,这种情况有点和扩展DLL类似,在DLL运行的计算机上必须要MFC代码库的DLL。
如果是静态连接,常规DLL里面已经包含了需要的MFC代码,这样DLL的体积将比较大,但它可以在没有MFC代码库DLL的计算机上正常运行。
二、建立DLL利用Visual C++提供的向导功能可以很容易建立一个不完成任何实质任务的DLL,这里就不多讲了,主要的任务是如何给DLL添加功能,以及在客户程序中利用这个DLL1、导出类用向导建立好框架后,就可以添加需要导出类的.cpp .h文件到DLL中来,或者用向导创建C++ Herder File/C++ Source File。
为了能导出这个类,在类声明的时候要加“_declspe c(dllexport)”,如:class _declspec(dllexport) CMyClass{...//声明}如果创建的MFC扩展DLL,可以使用宏:AFX_EXT_CLASS:class AFX_EXT_CLASS CMyClass{...//声明}这样导出类的方法是最简单的,也可以采用.def文件导出,这里暂不详谈。
2、导出变量、常量、对象很多时候不需要导出一个类,可以让DLL导出一个变量、常量、对象,导出它们只需要进行简单的声明:_declspec(dllexport) int MyInt;_declspec(dllexport) extern const COLORREF MyColor=RGB(0,0,0);_declspec(dllexport) CRect rect(10,10,20,20);要导出一个常量时必须使用关键字extern,否则会发生连接错误。
注意:如果客户程序识别这个类而且有自己的头文件,则只能导出一个类对象。
如果在DLL 中创建一个类,客户程序不使用头文件就无法识别这个类。
当导出一个对象或者变量时,载入DLL的每个客户程序都有一个自己的拷贝。
也就是如果两个程序使用的是同一个DLL,一个应用程序所做的修改不会影响另一个应用程序。
我们在导出的时候只能导出DLL中的全局变量或对象,而不能导出局部的变量和对象,因为它们过了作用域也就不存在了,那样DLL就不能正常工作。
如:MyFunction(){_declspec(dllexport) int MyInt;_declspec(dllexport) CMyClass object;}3、导出函数导出函数和导出变量/对象类似,只要把_declspec(dllexport)加到函数原型开始的位置:_declspec(dllexport) int MyFunction(int);如果是常规DLL,它将和C写的程序使用,声明方式如下:extern "c" _declspec(dllexport) int MyFunction(int);实现:extern "c" _declspec(dllexport) int MyFunction(int x){...//操作}如果创建的是动态连接到MFC代码库DLL的常规DLL,则必须插入AFX_MANAGE_STATE作为导出函数的首行,因此定义如下:extern "c" _declspec(dllexport) int MyFunction(int x){AFX_MANAGE_STATE(AfxGetStaticModuleState());...//操作}有时候为了安全起见,在每个常规DLL里都加上,也不会有任何问题,只是在静态连接的时候这个宏无效而已。
这是导出函数的方法,记住只有MFC扩展DLL才能让参数和返回值使用MFC的数据类型。
4、导出指针导出指针的方式如下:_declspec(dllexport) int *pint;_declspec(dllexport) CMyClass object = new CMyClass;如果声明的时候同时初始化了指针,就需要找到合适的地方类释放指针。
在扩展DLL中有个函数DllMain()。
(注意函数名中的两个l要是小写字母),可以在这个函数中处理指针:# include "MyClass.h"_declspec(dllexport) CMyClass *pobject = new CMyClass;DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved){if(dwReason == DLL_PROCESS_ATTACH){.....//}else if(dwReason == DLL_PROCESS_DETACH){delete pobject;}}常规DLL有一个从CWinApp派生的类对象处理DLL的开和关,可以使用类向导添加InitIns tance/ExitInstance函数。
int CMyDllApp::ExitInstance(){delete pobject;return CWinApp::ExitInstance();}三、在客户程序中使用DLL编译一个DLL时将创建两个文件.dll文件和.lib文件。
首先将这两个文件复制到客户程序项目的文件夹里,这里需要注意DLL和客户程序的版本问题,尽量使用相同的版本,都使用RELEASE或者都是DEBUG版本。
接着就需要在客户程序中设置LIB文件,打开Project Settings--- >Link--->Object/lib rary Modules中输入LIB的文件名和路径。
如:Debug/SampleDll.lib。
除了DLL和LIB文件外,客户程序需要针对导出类、函数、对象和变量的头文件,现在进行导入添加的关键字就是:_declspec(dllimport),如:_declspec(dllimport) int MyFunction(int);_declspec(dllimport) int MyInt;_declspec(dllimport) CMyClass object;extern "C" _declspec(dllimport) int MyFunction(int);在有的时候为了导入类,要把相应类的头文件添加到客户程序中,不同的是要修改类声明的标志:class _declspec(dllimport) CMyClass,如果创建的是扩展DLL,两个位置都是:class AFX_EXT_CLASS CMyClass。
使用DLL的一个比较严重的问题就是编译器之间的兼容性问题。
不同的编译器对c++函数在二进制级别的实现方式是不同的。
所以对基于C++的DLL,如果编译器不同就有很麻烦的。
如果创建的是MFC扩展DLL,就不会存在问题,因为它只能被动态连接到MFC的客户应用程序。
这里不是本文讨论的重点。
一、重新编译问题我们先来看一个在实际中可能遇到的问题:比如现在建立好了一个DLL导出了CMyClass类,客户也能正常使用这个DLL,假设CMyCla ss对象的大小为30字节。
如果我们需要修改DLL中的CMyClass类,让它有相同的函数和成员变量,但是给增加了一个私有的成员变量int类型,现在CMyClass对象的大小就是34字节了。
当直接把这个新的DLL给客户使用替换掉原来30字节大小的DLL,客户应用程序期望的是30字节大小的对象,而现在却变成了一个34字节大小的对象,糟糕,客户程序出错了。
类似的问题,如果不是导出CMyClass类,而在导出的函数中使用了CMyClass,改变对象的大小仍然会有问题的。
这个时候修改这个问题的唯一办法就是替换客户程序中的CMyClass 的头文件,全部重新编译整个应用程序,让客户程序使用大小为34字节的对象。
这就是一个严重的问题,有的时候如果没有客户程序的源代码,那么我们就不能使用这个新的DLL了。
二、解决方法为了能避免重新编译客户程序,这里介绍两个方法:(1)使用接口类。
(2)使用创建和销毁类的静态函数。
1、使用接口类接口类的也就是创建第二个类,它作为要导出类的接口,所以在导出类改变时,也不需要重新编译客户程序,因为接口类没有发生变化。
假设导出的CMyClass类有两个函数FunctionA FunctionB。
现在创建一个接口类CMyInter face,下面就是在DLL中的CMyInterface类的头文件的代码:# include "MyClass.h"class _declspec(dllexport) CMyInterface{CMyClass *pmyclass;CMyInterface();~CMyInterface();public:int FunctionA(int);int FunctionB(int);};而在客户程序中的头文件稍不同,不需要INCLUDE语句,因为客户程序没有它的拷贝。