四种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++类),这样就解决了这个问题。
四种DLL:NON-MFC DLL, Regular DLL Statically/Dynamically Linked to MFC, MFC Extension DLL的更多相关文章
- MFC 在对话框显示图片的多种方法(四种方法)
我们先从简单的开始吧.先分一个类: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) 为方便说明,我们已经建好一个基 ...
- WinDbg常用命令系列---.load, .loadby (Load Extension DLL)
.load, .loadby (Load Extension DLL) 简介 .load和.loadby命令将新的扩展DLL加载到调试器中. 使用形式 .load DLLName !DLLName.l ...
- .Net,Dll扫盲篇,如何在VS中调试已经编译好的dll?
什么是Dll? DLL 是一个包含可由多个程序同时使用的代码和数据的库. 例如,在 Windows 操作系统中,Comdlg32 DLL 执行与对话框有关的常见函数.因此,每个程序都可以使用该Dll中 ...
- 错误 1 无法将程序集“NBear.Data.dll”复制到文件“D:\newbpm\bpm\SureBpm\Bin\NBear.Data.dll”。无法将“D:\newbpm\bpm\SureSoft.WebServiceBaseLib\bin\Debug\NBear.Data.dll”添加到网站。 无法添加文件“Bin\NBear.Data.dll”。 拒绝访问。 D:\..
错误 1 无法将程序集“NBear.Data.dll”复制到文件“D:\newbpm\bpm\SureBpm\Bin\NBear.Data.dll”.无法将“D:\newbpm\bpm\SureSof ...
- Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)
Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...
- C#播放声音的四种方法 +AxWindowsMediaPlayer的详细用法
C#播放声音的四种方法 第一种是利用DirectX 1.安装了DirectX SDK(有9个DLL文件).这里我们只用到MicroSoft.DirectX.dll和 Microsoft.Directx ...
- 细说Mysql四种安装方法及自动化部署
一.简介 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库, 每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 我们也可以将数据存储在文件中,但是 ...
- VBA中四种自动运行的宏以及模块的含义
在Excel的“标准模块”中可以创建4种自动运行的宏,它们分别是Auto_Open(打开工作 簿时自动运行), Auto_Close, Auto_Activate, Auto_Deactivate. ...
- JDBC驱动的四种类型
Java中的JDBC驱动可以分为四种类型,包括JDBC-ODBC桥.本地API驱动.网络协议驱动和本地协议驱动. JDBC驱动类型一.JDBC-ODBC桥 JDBC-ODBC 桥 是sun公司提供的, ...
随机推荐
- mysql下面的INSTALL-BINARY的内容,所有的mysql的配置内容都在这
2.2 Installing MySQL on Unix/Linux Using Generic Binaries Oracle provides a set of binary distributi ...
- Nvidia Anisotropic Lighting
http://http.download.nvidia.com/developer/SDK/Individual_Samples/DEMOS/Direct3D9/HLSL_Aniso.zip Anis ...
- PHP Error 和 Logging 函数
PHP Error 和 Logging 函数 PHP Error 和 Logging 简介 Error 和 Logging 函数允许您对错误进行处理和记录. Error 函数允许用户定义错误处理规则, ...
- thinkphp的save方法失败
如果用下面的方式更新数据时, $data['link_phone'] = I('post.link_phone'); $flag1 = $order->save ($data); $data一定 ...
- 1 2 3 n
n(n+1)/2 连续自然数 1,2,3.....,n 队列 从中任意取出1至n个相加,可以表示的连续自然数队列中最大的自然数是多少 受"高斯求和--蛇头蛇尾脑图--长方形对角线脑图--苯环 ...
- Nginx目录别名(Alias)支持PHP的配置
需求:通过 example.com 访问 /var/data/www,但通过 example.com/pa 访问的却是 /var/data/phpmyadmin,即保护phpmyadmin不暴露在ww ...
- perl常用代码
字符串联结和重复操作符 联接: . 重复:x 联接且赋值(类似+=): .=例: $newstring = "potato" . "head"; $ ...
- 【转】Xamarin.Android 入门之:Xamarin+vs2015 环境搭建
Xamarin.Android 入门之:Xamarin+vs2015 环境搭建 一.前言 此篇博客主要写了如何使用搭建xamarin开发的环境,防止我自己万一哪天电脑重装系统了,可以直接看这篇博客 ...
- phpexcel 读取数据
最近公司做一个客户导入会员的功能,以前导入都是使用csv格式导入的,但是客户反应问题挺多的,普遍是乱码(由于各种系统各种环境可能引起编码问题).最近想着就把这个导入完全改成excel导入,就研究了下p ...
- nrf51822裸机教程-PWM
先简单介绍一下PWM的原理. 原理很简单. 假设COUNTER是个从0开始递增的计数器. 我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转 ...