MFC创建DLL

来源:互联网 发布:黑白照片的魅力 知乎 编辑:程序博客网 时间:2024/05/29 12:21

MFC常规DLL的创建与使用实例

标签: MFC DLL 调用 调试
8382人阅读 评论(0)收藏举报
分类:
作者同类文章X
    

    MFC常规DLL的创建与使用实例

    22.2节中介绍了非MFC DLL的创建和使用实例,与之不同的是,本节介绍内部使用MFC,但是提供的访问接口不支持DLL而是标准的C接口的常规DLL。除了介绍基本概念和创建方法外,本节还介绍MFC常规DLL的创建实例和调用方法。

    22.3.1 基本概念

    MFC常规DLL,从字面上理解有两点。一是MFC的,这是指DLL内部使用MFC进行编程。二是指其是常规的,这是指此种DLL提供的接口是常规的而不是DLL的。从这种类型的DLL中导出的函数可以被MFC也可以被非MFC应用程序调用,从其中导出的函数使用标准的C接口。

    MFC常规DLL具有一个对应的CwinApp对象,并且初始化和析构任务与MFC应用程序的处理位置是相同的,分别在DLLCwinApp派生类的InitInstance()成员函数和ExitInstance()成员函数中处理。因为MFC提供了DllMain()函数,因此,不需要手动编写此函数。DllMain()函数在DLL装载时,调用InitInstance()函数,在DLL卸载时,调用ExitInstance()函数。MFC常规DLL分为两种,分类标准是链接MFCDLL的方式。

    静态链接MFC的规则DLL,在内部使用MFC,使用MFC的静态链接库生成DLL

    动态链接MFC的规则DLL,在内部使用MFC并动态链接到MFC。使用此方式的规则DLL,则必须在DLL的所有导出的函数的开头使用AFX_MANAGE_STATE宏,设置当前模块状态为DLL中的一个。

    MFC常规DLL的创建

    VC 6.0中创建MFC常规DLL步骤如下:

    1)打开VC,选择File |New命令,弹出New对话框,选择其中的Projects选项卡,如图22-9所示。

    http://images.51cto.com/files/uploadimg/20100804/164653280.jpg 

    22-9 创建MFC常规DLL的第一步

    2)在Project Name文本框和Location文本框中填入相应的值,并选择MFC AppWizard(dll)图标。单击OK按钮,弹出MFC AppWizard-Step 1 of 1对话框,如图22-10所示。

    3What type of DLL would youlike to create选项组中选择创建的DLL种类。其中,Regular DLL with MFC statically linked单选按钮表示创建静态链接到MFC的规则DLLRegularDLL using shared MFC DLL单选按钮表示创建动态链接到MFC的规则DLLMFC Extension DLLusing shared MFC DLL)单选按钮表示创建MFC扩展DLL。此处选择动态链接到MFC的规则DLL。其中,Automation复选框表示是否添加自动化支持,即可以在此工程中,直接运行其他程序。WindowsSockets复选框表示是否添加对Socket的支持。Wouldyou like to generate source file comments选项组表示是否为源文件生成注释。单击Finish按钮,弹出New Project Information对话框,如图22-11所示。

    http://images.51cto.com/files/uploadimg/20100804/164739100.jpg 

    22-10 创建MFC常规DLL的第二步

     

    http://images.51cto.com/files/uploadimg/20100804/164800870.jpg 

    22-11 创建MFC常规DLL的第三步

    4)单击OK按钮,这样就成功地创建了一个MFC常规DLL

    在创建了DLL后,就可以将程序功能添加到DLL中。

    MFC常规DLL的创建实例

    22.3.2小节介绍了创建MFC常规DLL的方法,本小节以一个实例讲解具体过程。在本小节实例实现的功能是创建一个通过MFC实现的对话框类,并在导出的接口函数中调用此对话框。具体过程为:

    1)按照22.3.2小节中介绍的方法,创建MFC常规DLL

    2)在DLL工程中按照前面讲过的方法,添加一个对话框资源,并为此对话框资源创建派生自Cdialog类的对话框实例类,并在对话框内添加实现的功能。本实例中,实现单击对话框类中的按钮,则在静态框中显示欢迎词的功能。

    3)添加调用此对话框的接口函数。接口函数需要使用extern"C"__declspec(dllexport)修饰符指定,使其作为导出接口函数。代码如下:

    1. extern "C" __declspec(dllexport) void ShowDlg(void) // 显示对话框  

    2. {  

    3.     AFX_MANAGE_STATE(AfxGetStaticModuleState()); 

    4.     CdlgDllTest dlg;            // 定义对话框变量  

    5.     dlg.DoModal();              // 显示对话框  

    6. 

    需要注意的是,此处在调用CdlgDllTest对话框前,需要调用AFX_MANAGE_STATE宏,此宏的功能是进行模块状态的切换,而AfxGetStaticModuleState()函数是在程序堆栈上创建一个AFX_MODULE_STATE类型的实例,以切换当前运行的模块状态。在动态链接MFC的常规DLL的每个接口函数中都需要调用此语句,或是在调用DLL的地方使用资源切换的方式(这种方式在第22.2节中介绍过)。不管哪种方式都需要进行运行程序状态切换,才可以完成对资源对话框的调用。

    4)添加完功能代码,编译链接DLL,生成RegMFCDLLSample.dll即可。

    MFC常规DLL的调用

    创建完MFC常规DLL后,就可以在应用程序中调用它了。MFC常规DLL既可以被MFC应用程序调用,也可以被非MFC应用程序调用。调用MFC常规DLL的方式有两种,一种是静态引用,通过加载静态链接库的lib文件实现。一种是动态引用,动态加载DLL后,获取要调用的函数地址,然后执行相应的函数。本节以动态加载的方式演示如何调用MFC常规DLL。代码如下:

    1. void CRegMFCDllTestDlg::OnButtonInvokedll()      
    // 
    调用DLL  

    2. {  

    3.     typedef void (*pFunction)(void);// 定义函数变量  

    4.     HINSTANCE hLibrary;             // DLL句柄  

    5.     hLibrary = LoadLibrary("RegMFCDLLSample.dll");  
    // 
    装载DLL  

    6.     if (hLibrary == NULL)   MessageBox("DLL加载
    失败");  // 提示错误信息  

    7.     pFunction pShowDlg = (pFunction)GetProcAddress
    (hLibrary,"ShowDlg");  

    8. // 执行函数  

    9.     if (NULL==pShowDlg) MessageBox("DLL中不存在指
    定的函数"); // 输出提示  

    10.    else pShowDlg(); 

    11.

    上面代码定义了函数指针变量pFunction。调用LoadLibrary()函数装载要执行的DLL,此处是RegMFCDLLSample.dll。如果加载成功,使用GetProcAddress()函数获取要执行的接口函数的地址,如果查找到函数,则执行。程序运行的效果如图22-12所示。

    http://images.51cto.com/files/uploadimg/20100804/165156808.jpg 

    22-12  MFC常规DLL调用实例运行效果图

     

    MFC扩展DLL的创建与使用实例

    MFC常规DLL是使用MFC但是导出的接口不支持MFCDLL,而MFC扩展DLL则是内部既使用MFC,导出的接口也支持MFCDLL,解决了要在DLLEXE之间传递从MFC派生而来的类的问题。本节介绍MFC扩展DLL的创建和使用实例。

    22.4.1  MFC扩展DLL的创建

    MFC扩展DLL实现继承子MFC类库中的已经存在的类,完成可重复使用的类的DLL。扩展DLL使用MFC的动态链接版本,也就是MFC共享版本。只有使用MFC共享版本生成的MFC可执行文件(应用程序或规则DLL),可以使用扩展DLL。使用扩展DLL可以从MFC中继承新的自定义类,并为应用程序提供扩展的MFC版本。

    DLL的客户端EXE必须是使用_AFXDLL编译的MFC应用程序。

    动态链接到MFC的规则DLL也可以使用扩展DLL

    扩展DLL也可以使用_AFXEXT定义进行编译,强制定义_AFXDLL,并保证正确的特性。使得当生成DLL时,AFX_EXT_CLASS定义为__declspec(dllexport),如果在扩展DLL中使用宏声明类则是必需的。

    扩展DLL不会实例化从CwinApp继承的类,但是依赖于客户端应用程序或DLL提供对象。

    扩展DLL也提供一个DllMain()函数,并进行必需的初始化工作。

    扩展DLL使用MFC的动态链接版本生成(也就是共享MFC版本)。只有使用共享版本MFCMFC可执行程序(应用程序或规则DLL)才可以使用扩展DLL。无论是客户端应用程序还是扩展DLL,必须使用相同的MFC.DLL版本。

    扩展DLL可以在应用程序和DLL之间传递派生自MFC的对象。在对象创建的模块中与传入对象相关的成员函数也会传入。因为当使用共享MFCDLL版本时,这些函数被正确地导出,可以在应用程序和导入的扩展DLL之间自由地传递MFC或派生的MFC对象指针。

    MFC扩展DLL使用共享版本的MFC与应用程序使用共享版本的DLL的方法是相同的,但是也有不同之处。

    没有继承子CwinApp的派生类。必须与客户端应用程序的CwinApp派生对象一起工作。也就是说,客户端应用程序处理主消息队列、空闲队列等。

    DllMain()函数中调用AfxInitExtensionModule()函数,并检测此函数的返回值。如果此函数返回0,则从DllMain()函数中返回0

    如果扩展DLL想导出应用程序的CruntimeClass对象或资源,则会在初始化时,创建CdynLinkLibrary对象。

    如果使用DEF文件导出,在头文件的开头和结尾处放置以下代码。

    1.  #undef AFX_DATA  
    2.  #define AFX_DATA AFX_EXT_DATA  
    3.  // 头文件体  
    4.  #undef AFX_DATA  
    5.  #define AFX_DATA 

    4行可以保证扩展DLL中的代码正确编译。如果没有这4行,会导致DLL编译或链接不正确。创建MFC扩展DLL的方法与创建MFC常规DLL的步骤基本是相同的,只是在创建MFC DLL的第一步中,选择DLL的类型为MFC Extension DLLusingshared MFC DLL选项,则创建的DLL就是MFC扩展DLL

    MFC扩展DLL的创建实例

    22.4.1小节介绍了创建MFC扩展DLL的方法,本小节以一个实例讲解具体过程。在本小节实例实现的功能是创建一个通过MFC实现的对话框类,并在一个导出类中提供调用此对话框的接口函数。具体过程为:

    1)按照22.4.1小节中介绍的方法,创建MFC扩展DLL

    2)在DLL工程中按照前面讲过的方法,添加一个对话框资源,并为此对话框资源创建派生自Cdialog类的对话框实例类。并在对话框内添加实现的功能,本实例中,实现单击对话框类中的按钮,在静态框中显示欢迎词。

    3)添加调用此对话框的接口类。接口类需要使用AFX_EXT_CLASS修饰符指定,使其作为导出类。代码如下:

    1.  class AFX_EXT_CLASS  CExtDLLClass : Cobject  
    2.  {  
    3.      public:  
    4.             void ShowDlg();  
    5.             CExtDLLClass();  
    6.             virtual ~CExtDLLClass();  
    7.  }; 

    其中,在ShowDlg()函数中会调用自定义的对话框CDlgExtDLL。而自定义对话框类CDlgExtDLL可以按照普通的对话框程序一样设计使用。

    4)添加完功能代码,编译链接DLL,生成ExtMFCDLLSample.cpp.dll即可。

    MFC扩展DLL的调用

    创建完MFC扩展DLL后,就可以在应用程序中调用它了。MFC扩展DLL既可以被MFC应用程序调用,也可以被非MFC应用程序调用。调用MFC扩展DLL的方式是通过静态引用,即通过加载静态链接库的lib文件实现。要完成对MFC扩展DLL的调用,需要3个资源。

    包含要调用的类的头文件,在本例中是ExtDLLClass.h文件。

    需要加载MFC扩展DLL对应的静态链接库LIB文件,在本例中是ExtMFCDLLSample.lib文件。

    MFC扩展DLL的动态链接库,在本例中是ExtMFCDLLSample.dll文件。代码如下:

    下面代码表示调用MFC扩展DLL中的接口类提供的对话框功能。

    1. void CExtMFCDLLTestDlg::OnButtonInvokedlg()     // 调用DLL中的对话框  

    2. {  

    3.     CExtDLLClass dlg;           // 定义对话框变量  

    4.     dlg.ShowDlg();          // 显示对话框  

    5. 

    从上面可以看出,在调用MFC扩展DLL的时候,调用方法与普通的MFC类调用的方式是相同的。在本例中,DLL导出的类是继承自MFCCobject类,同样也可以导出派生自MFC的其他类。程序运行效果如图22-13所示。

    http://images.51cto.com/files/uploadimg/20100804/1701410.jpg 

    22-13 调用MFC扩展DLL的运行效果图

    DLL的查看与调试

    Windows操作系统的核心功能是采用模块的方式实现的。它将各种相关功能放置在同一DLL模块中。因此,每个应用程序都会调用相关的系统的或用户自定义的DLL。因此,在编写程序时,就必须掌握DLL的查看和调试的方法。

    22.5.1 使用Depends工具查看DLL接口

    VC 6.0提供了查看DLL接口的工具--Depends。调用方法是选择"开始"|"所有程序"|"MicrosoftVisual Studio 6.0"|"Microsoft Visual Studio 6.0Tools"|"Depends"命令,即可打开Depends工具。要查看DLL接口,则选择"File"|"Open"命令,选择要查看的DLL文件,则界面中会显示DLL调用的DLL及其提供的接口,如图22-14所示。

    http://images.51cto.com/files/uploadimg/20100804/170516423.jpg 

    22-14  Depends工具运行界面图

    在图22-14中,显示了在22.3中创建的DLL的接口。其中左边树形视图,显示了DLL调用的所有其他DLL的列表。右边列表部分显示了查看的DLL提供的接口函数。底部的列表视图显示了调用的DLL模块的信息。在左边树形视图中,选择相应的DLL,在右边的列表部分,会显示对应的接口函数的列表。其中,Ordinal列表示函数在DLL中的序号或名称,Hint列表示接口函数在DLL内部的序号值,Function列表示函数名称,Entry Point列表示函数入口点。从图22-15中可以看到,REGMFCDLLSAMPLE.DLL中提供了ShowDlg()接口函数。用户可以使用此工具查看指定DLL所调用的其他DLL和指定DLL提供的接口函数。

    DLL的调试

    在编写的程序,一定会遇到需要调试的情况。DLL的调试与EXE调试是类似的,但是在EXE调试时,可以直接在要调试的代码行上加上断点进行调试。当EXE调用DLL时,使用静态链接的方法调用DLL接口,则可以在DLL需要调试的源代码处设置断点,直接运行EXE程序,则程序运行到断点时,会中断以进行调试。但是如果动态加载在断点调试就比较困难。如果要专门调试某个DLL,则可以通过以下两种方式设置调试DLL的宿主程序。

    1)通过选择Project|Settings命令,弹出Project Settings对话框。选择Debug选项卡,在Executable for debug session文本框中选择要运行用于调试DLL的可执行文件,如图22-15所示。

    2)直接运行DLL工程,则会弹出Executable For Debug Session对话框。在Executablefile name文本框中选择要运行用于调试DLL的可执行文件,如图22-16所示。

    设置好了宿主程序,在DLL源代码中要调试的代码行上加入断点,并运行宿主程序,则程序运行到DLL的断点处会中断等待进行调试。

    除了加断点进行调试的方法外,其他的调试方法在DLL中与在EXE中进行调试的方法是一样的。熟练掌握程序调试的方法,可以加快程序的开发效率,并且可以提高代码质量。

    http://images.51cto.com/files/uploadimg/20100804/170822916.jpg 

    22-15 设置DLL调试的宿主程序

     

    http://images.51cto.com/files/uploadimg/20100804/170835548.jpg 

    22-16 运行设置DLL调试的宿主程序

     

    2
    0
     
     

      相关文章推荐
    • 创建并调用MFC规则DLL的实例
    • Presto服务治理与架构优化在京东的实践应用--王哲涵
    • VS2010下生成dll的方法
    • 【免费直播】Python最佳学习路线--韦玮
    • 创建一个MFC动态链接库
    • JS-SDK开发与微信支付
    • 在VS2015中用C++创建MFC规则动态库DLL
    • Spring Cloud微服务真实场景实战解析
    • VC++6.0如何创建与调用动态链接库(dll)
    • 10小时深入掌握 Kubernetes
    • 基于VC6.0的DLL开发
    • JDK9新特性
    • 三种DLL(Win32DLL,MFC常规DLL和MFC拓展DLL)的简单学习总结
    • MFC DLL 的初始化入口函数:
    • 站在富士康的厂房里看建造者设计模式
    • 十三种基于直方图的图像全局二值化算法原理、实现、代码及效果。
    原创粉丝点击