zoukankan      html  css  js  c++  java
  • 四种DLL:NON-MFC DLL, Regular DLL Statically/Dynamically Linked to MFC, MFC Extension DLL

    参考资料:

    https://msdn.microsoft.com/en-us/library/30c674tx.aspx

    http://www.cnblogs.com/qrlozte/p/4844429.html

    http://www.cnblogs.com/qrlozte/p/4850642.html

    在上面给出的MSDN链接中,你可以看到四种DLL的定义。这里就不赘述。捡重点的说

    区别就在于:

    • NON-MFC DLL内部不能使用MFC(当然其导出的API也不能涉及MFC)。(这里我说“导出的API”是指导出的C函数、C++类或者共享的全局变量等等)
    • Regular DLL Statically/Dynamically linked to MFC内部可以使用MFC,但是其导出的API不能涉及MFC(比如说涉及到MFC的某个类或其子类,包括你写的MFC的子类,以及任何没有在该DLL中运行的MFC代码;说人话,就是任何涉及MFC的代码都只能在DLL内部运行,如果你从DLL中导出,再由其他的EXE或者DLL运行,是不行的。)当然,根据该DLL是动态链接到MFC库还是静态链接到MFC库又细分成了两种。
    • MFC Extension DLL内部可以使用MFC,并且其导出的API也可以涉及MFC。
    • 可以看到,从NON-MFC DLL到MFC Extension DLL,其可使用的功能越来越多。NON-MFC DLL可以导出C函数,全局变量,普通的C++类,但不能涉及MFC;Regular DLL具备NON-MFC DLL的所有能力,并且其内部可以使用MFC,但不能将涉及MFC的部分导出;MFC Extension DLL具备Regular DLL的所有能力,并且可以导出使用MFC的API。

    1、如何在VS中创建四种DLL的项目

    1.1、NON-MFC DLL

    新建项目>VC++>Win32>Win32项目>选择DLL

    1.2、Regular DLL Statically/Dynamically linked to MFC

    新建项目>VC++>MFC>MFC DLL>选择Statically linked to MFC / Dynamically linked to MFC

    1.3、MFC Extension DLL

    新建项目>VC++>MFC>MFC DLL>选择MFC Extension DLL

    DLLDEMO项目:

    举例说明了NON-MFC DLL(AddXxx.dll):导出了C函数,全局变量,非MFC的C++类。

    举例说明了Regular DLL Dynamically linked to MFC(Add.dll):导出了C函数,一个非MFC的C++类,二者都可以在其内部使用MFC创建一个对话框。并且通过InfoDlgFactory说明了为什么Regular DLL不能把MFC类导出。见InfoDlg.cpp中InfoDlgFactory的注释。

    举例说明了MFC Extension DLL(AddExt.dll):导出了C函数,MFC子类,该子类是一个对话框。

    测试程序:FontView.exe,点击Print Sample按钮可以测试三种DLL,相关代码在CMainWindow::OnPushButtonClicked中可以看到

    下载地址:下载DLLDEMO

    备注:

    1、AFX_MANAGE_STATE的作用

    https://msdn.microsoft.com/en-us/library/0asx94f7.aspx

    https://msdn.microsoft.com/en-us/library/30c674tx.aspx

    简单来说,假设你的项目有一个a.EXE,b.DLL,  c.DLL,a动态链接到b,b动态链接到c,那么实际上a,b,c是三个模块。当代码执行路径(code path)从a到b或者从b到c的时候,涉及到一个“模块状态”的切换,当然这个“模块状态”要掰开揉碎了说就能说上一天也不一定说的完了,总之AFX_MANAGE_STATE就是干这个事的。如果没有它就会出现各种错误。

    在编写AddExt.dll的代码的时候,由于没仔细看MSDN中的说明,在InfoDlgFactoryExt中使用了AFX_MANAGE_STATE从而导致了LNK2005错误(error LNK2005: _DllMain@12 already defined in dllmain.obj)。实际上MFC Extension DLL用不着这个,AFX_MANAGE_STATE只是拿给动态链接到MFC的Regular DLL用的(https://msdn.microsoft.com/en-us/library/30c674tx.aspx;“The AFX_MANAGE_STATE macro should not be used in regular DLLs that statically link to MFC or in extension DLLs. ”)。

    2、什么地方需要使用AFX_MANAGE_STATE

    前提条件,DLL是动态链接到MFC库的regular dll。并且,涉及到模块切换的地方,也就是说只要涉及到一个模块调用实现在另一个模块内的代码,并且这个代码调用了MFC库的代码的时候。就应该使用AFX_MANAGE_STATE。下面举例说明

    打开Add项目,查看CInfoDlg和DoModalDlgImpl的定义

    class CInfoDlg : public CDialog, public IInfoDlg

    查看IInfoDlg的定义就知道,IInfoDlg纯粹是一个interface,里面只有pure virtual函数,作为Add.dll的接口用。CDialog是MFC类。所以CInfoDlg也是MFC类,因此CInfoDlg的创建、使用、销毁都会调用MFC库。

    因此IInfoDlg的DoModalDlg和Release以及InfoDlgFactory都会调用MFC库。所以这三个方法都使用了AFX_MANAGE_STATE

    class DoModalDlgImpl : public IDoModalDlg

    IDoModalDlg也是一个interface,所以DoModalDlgImpl只是一个普通的C++类。其创建、使用和销毁会不会调用MFC库取决于它的实现。

    现在去看DoModalDlgImpl的实现。

    可以看到只有DoModalDlgImpl::DoModalDlg里面创建了CInfoDlg并且调用了CInfoDlg::DoModal,所以只有DoModalDlgImpl::DoModalDlg会调用MFC库。

    因此,可以看到,DoModalDlgImpl相关的DoModalDlg、Release、DoModalDlgFactory,只有DoModalDlg需要使用AFX_MANAGE_STATE。

    3、为什么不要直接export一个DLL中的C++类,或者MFC类

    http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

    一个C++类(MFC类也不例外)包含两个部分,interface和implementation,即接口和实现,public和protected的部分属于interface(protected部分仅仅对子类来说是interface)。

    看上面引用的文章“What you see is not what you get”

    你把实现在一个DLL中的类导出,目的是导出它的接口,而不是实现。但是,直接用__declspec(dllexport)导出一个C++类不仅把其接口部分给导出,其实现部分也给导出了,所以,假设一个类的实现用到了其他的类(比如说通过继承或者通过成员),这些部分也会被导出,这个过程会一直进行下去,所以这样一来你本来只想导出3个方法,结果导出了万八千个你不想导出的东西。

    这就是为什么在DLLDEMO中,接口部分都用的interface(只有pure virtual函数的C++类),这样就解决了这个问题。

  • 相关阅读:
    贪心法解活动安排问题
    求两个等长的已排序数组的中位数(《算法导论》P113习题9.3-8)
    0-1背包问题
    动态规划法解最长公共子序列问题
    动态规划法解矩阵链乘问题
    常见的算法设计策略
    A*算法与8数字谜题(参见《算法》P226习题2.5.32)
    keepalive+redis 主从高可用
    sharding-jdbc 读写分离+水平分表
    hash一致算法原理
  • 原文地址:https://www.cnblogs.com/qrlozte/p/4852093.html
Copyright © 2011-2022 走看看