2 MFC DLL——扩展的和正规的
MFC的AppWizard可以让我们创建MFC库支持的两种DLL:扩展的DLL和正规的DLL。这两种类型的区别是什么呢?
说明:当然,Developer Studio也让我们创建纯的、与MFC库无关的Win32 DLL,就像它让我们创建与MFC库无关的Windows程序一样。
²扩展DLL支持C++接口,换句话说,该DLL可以导出整个类,客户可以构造这些类的对象或从这些类进行派生。扩展DLL动态连接到MFC库的DLL版本的代码,因此,扩展DLL要求客户程序被动态连接到MFC库(AppWizard默认设置),并且客户程序和扩展DLL要一致连接到MFC DLL的相同版本(mfc42.dll、mfcd42.dll等)。扩展DLL很小,我们可以创建一个简单的扩展DLL,大约10KB左右,它的装载会很快。
²如果我们需要一个DLL,并希望它可以被任何Win32编程环境(包括Visual Basic 5.0)装载,那么我们必须使用正规DLL。这里有一个很大的限制就是,正规DLL可以导出C风格的函数,但不能导出C++类、成员函数或重载函数,因为每一个C++编译器都有自己修饰名字的方法。不过,我们可以在正规DLL内部使用C++类(特别是MFC库的类)。
当我们创建MFC正规DLL时,我们可以选择静态连接或动态连接到MFC库。如果选择了静态连接,DLL将包括所有它需要的MFC库代码的拷贝,因此它可以独立于MFC库。一个典型的Release版本静态连接的正规DLL大约为144KB左右。如果选择动态连接,大小可降到17KB左右,但必须保证适当的MFC DLL在目标机器上存在。
当我们指定AppWizard创建DLL或EXE的类型时,编译器#define常量将按下表设置:
|
动态连接到共享的MFC库
|
静态连接到MFC库
|
正规DLL
|
_AFXDLL、_USRDLL
|
_USRDLL
|
扩展DLL
|
_AFXEXT、_AFXDLL
|
不支持
|
客户EXE
|
_AFXDLL
|
没有定义常量
|
如果我们查看MFC源代码和头文件,将会看到大量的这些常量的#ifdef语句。这表明库代码的编译也是非常不同的,具体取决于我们产生工程时指定的类型。
2.1共享的MFC DLL和Windows DLL
²如果我们使用共享MFC DLL选项创建一个Windows的Debug目标的程序,则该程序将动态连接到下列一个或多个(ANSI)MFC DLL:
mfc42d.dll
|
核心MFC类
|
mfco42d.dll
|
ActiveX(OLE)类
|
mfcd42d.dll
|
数据库类(ODBC和DAO)
|
Mfcn42.dll
|
Winsock和WinInet类
|
²当创建Release目标时,程序只是动态连接到mfc42.dll。对这些MFC DLL的连接都是通过导入库隐式连接。我们也可以假定隐式连接到Windows里的ActiveX和ODBC的DLL,这种情况下,我们可以认为当装入用Release目标创建的客户时,所有这些DLL都被连接到了程序中,而不管客户是否使用了ActiveX和ODBC特性。然而,实际情况并不是这样。通过一些创造性的手段,当这些函数中的某一个首先被调用时,MFC会显示装入ActiveX和ODBC DLL(通过调用LoadLibrary)。这样客户程序只是装入自己所需要的DLL。
2.2 MFC扩展DLL——导出类
如果扩展DLL只包含被导出的C++类,那么我们可以很方便地创建和使用该DLL。创建EX21A示例程序(P433)的步骤显示了如何让AppWizard创建一个扩展DLL的框架。该框架只有DllMain函数,我们只要简单地把C++类加到工程里。但有一件特殊的事情我们必须要做,即我们必须把宏AFX_EXT_CLASS加到类声明中,如下所示:
- classAFX_EXT_CLASSCstudent:publicCobject
不仅对DLL工程中的H文件要作这样的修改,对客户程序使用的H文件同样也要作修改。换句话说,H文件对于客户和DLL是一样的。该宏根据相应条件会产生不同的代码——在DLL里导出类,在客户程序里导入类。
2.3 MFC扩展DLL资源搜索的顺序
如果我们创建一个动态连接到MFC的客户程序,许多MFC库的标准资源(错误信息字符串和打印预览对话框模板等)都被保存在MFC DLL里(mfc42.dll、mfcd42.dll等),但应用程序也有自己的资源。当程序调用一个MFC函数(如Cstring::LoadString或Cbitmap::LoadBitmap)时,框架首先搜索EXE的资源,然后搜索MFC DLL的资源。
如果程序包含一个扩展的DLL,并且EXE需要一个资源,则搜索顺序为:首先是EXE文件,然后是扩展DLL,再是MFC DLL。例如我们有一个字符串资源ID,在所有资源中它是唯一的,则MFC库将会找到该资源。如果在EXE文件和扩展DLL文件里有重复的字符串ID,则MFC库会装入EXE文件里的字符串。
如果扩展DLL装入一个资源,则搜索序列为:首先是扩展DLL,然后是MFC DLL,再是EXE。
说明:如果需要的话,我们可以改变搜索序列。假定我们希望EXE代码首先搜索扩展DLL的资源,则可以使用下面的代码:
我们不能用AfxGetInstanceHandle代替::GetModuleHandle。在一个扩展DLL里,AfxGetInstanceHandle返回的是EXE的实例句柄,而不是DLL的句柄。
2.4如何使用MFC扩展DLL
u将一个独立的类MyClass,做成一个扩展的DLL
a)首先制作一个单独的功能简单的类,内容如下:
b)然后,运行AppWizard产生一个扩展的DLL,通过选择MFC AppWizard(dll)->MFC Extension DLL->Finish,工程名为ex21a。
c)将MyClass.h和MyClass.cpp这两个文件拷贝到刚才创建的工程中,通过Project->Add to Project->Files。添加后,编辑MyClass.h文件如下:
d)最后编译工程,得到了我们需要的两个文件ex21a.dll和ex21a.lib。
uDLL测试客户程序
a)运行AppWizard产生一个Win32控制台程序,通过选择Win32 Console Application->工程名为client->一个空白工程,然后再新建一个C++ Source File,文件名为client。完成后,在client.cpp文件中添加如下测试代码:
b)修改设置,在Project->Settings->General->在Microsoft Foundation Classes中选择Use MFC in a Shared DLL。
c)将ex21a.dll、ex21a.lib和MyClass.h三个文件拷贝到client工程目录下,类似上述相同的方法,将MyClass.h添加到工程中,并且在Project->Settings->Link,在Object/library modules中添加ex21a.lib(多个lib用空格分开)。
d)修改MyClass.h文件的内容。当时我在调试的时候,出现了错误,需要小心。我们在扩展DLL工程中的MyClass.h文件中使用宏AFX_EXT_CLASS来声明导出类,而同时要在client工程中的MyClass.h文件中使用宏AFX_EXT_CLASS来声明导入类。但是在我编译client工程的时候问题出现了:
error C2079: 'CMyClass' uses undefined class 'AFX_EXT_CLASS'
提示AFX_EXT_CLASS没有定义,应该是少加头文件了。在网上g一下找到了一些相同的问题贴:
http://www.eggheadcafe.com/software/aspnet/29755654/problem-using-self-built.aspx
http://hi.baidu.com/qingdi963/blog/item/c75fa8501ffada878c5430b7.html/cmtid/24b28d832df3729af703a6c7#24b28d832df3729af703a6c7
http://msdn.microsoft.com/en-us/library/h5f7ck28.aspx(Extension DLLs)
http://msdn.microsoft.com/en-us/library/4fezhh3d.aspx(DLLHUSK Sample: Dynamically Links the MFC Library)
http://www.codeguru.com/Cpp/W-P/dll/article.php/c119(Using one extension DLL in another)
解决方法如下,修改MyClass.h文件内容为:
方法1:
方法2:
e)现在重新编译没问题了,可以得到如下的输出结果,即可以在client程序中成功地调用我们在扩展DLL中导出的类了。
main()
CMyClass::CMyClass()
SetValue(int n)
GetValue()
_a=100
wcdj于2010-1-6记下次总结MFC正规DLL的使用方法。
相关推荐
MFCDll调用例子,仅供学习交流用 包含dll工程和调用工程。
MFC代码——贪吃蛇,上大学时候的作业,估计大学生们可能会需要
本实例创建了MFC Dll,并在Dll内部启用Timer及线程,并通过Demo去调用。
该资源提供MFC常规DLL的定义,与使用方法,对初学者有一定帮助
教你首次使用 MFC 扩展DLL(导出类)的Demo
实用MFC教程——Windows常用控件的使用 适合初学VC/MFC
MFC案例————便签(对Mysql数据库的增删改查),ODBC连接数据库,左边菜单栏显示便签的序号,右边显示便签的内容和时间,点击查询可显示处理数据内容。 可以对便签进行添加和删除功能。
实用MFC教程——对话框,内容详细,适合初学者,大牛勿下
高手绕过, 这是一个使用规则mfc dll的小例子, 网上说的dll 大多是win32 的dll,没有mfc 的,给初学者带来困难 我最近要用,于是写了一个。。。有详细说明的
VS2015中用C++创建MFC DLL动态库,包含了mfc dll的创建以及在控制台中调用
MFC DLL规则库封装例程及其调用方法,包含静态调用和动态调用。
MFC 规则DLL 添加自定义的 DLLMAIN() 函数!(Vc6.0 与 Vc8.0 同样适用) 这也是我自己一直困扰了好久的问题,本来编程水平就不高,总想借助MFC的类库编写程序,方便不少啊!但是MFC规则DLL中却不提供DLLMAIN()函数...
mfc90d.dll mfc90d.dll mfc90d.dll mfc90d.dll mfc90d.dll mfc90d.dll
MFC规则DLL例子源码,VC6.0平台开发,亲自调试完成
【win32静lib/动态库DLL+MFC扩展DLL+Regular_DLL】完整实例代码 各种导出,各种调用,说明详细。
一个简单的调用MFC规则DLL的实例,有详细的代码注释和文档说明。欢迎学习编写MFC规则DLL(共享非静态)的同学们下载使用。
MFC 教程 作者:李久进 作者序 ----------- 我曾写一本关于MFC的书,分析了MFC的结构和设计(《MFC深入浅出》),华中理工大学出版。书的内容建立在对MSDN和MFC SOURCE CODE的大量分析上,该书对于希望学习MFC的人来...
mfc70.dll
MFC DLL开发和使用的例子,包括开发和使用MFC DLL的代码,很简单的示例,相关介绍文章见http://blog.csdn.net/sllins/archive/2010/04/27/5533764.aspx
MFCDLL 非模态.zip 界面封装DLL 并调用,非模态状态。两个界面相互不干扰,亲测可用。