四种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公司提供的, ...
随机推荐
- Transform-style和Perspective属性
transform-style属性 transform-style属性是3D空间一个重要属性,指定嵌套元素如何在3D空间中呈现.他主要有两个属性值:flat和preserve-3d. transfor ...
- gitlab & gerrit & git & repo & jenkins
Omnibus GitLab documentation(中文安装说明) 在自己的服务器上部署 GitLab 社区版->较为全面 GIT & REPO & GERRIT (三) ...
- 升级xcode6和ios8后,unity遇到的一些小问题
升级最新的Xocde6后,如果不是最新版本的unity,虽然也可以也可以正常的build,但如果想通过unity连真机进行profile的话,就会在xocde中报错,这个的主要原因是unity的配置里 ...
- [转]通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
http://www.csdn.net/article/2015-07-31/2825348 [编者按]时下,对于大部分IT玩家来说,Docker和Mesos都是熟悉和陌生的:熟悉在于这两个词无疑已成 ...
- 【转载】Http协议
HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1.0的第 ...
- javaWeb中struts开发——Logic标签
1.Struts标签的logic标签 Logic标签是逻辑标签,是Struts中比较重要的标签,完成各种逻辑运算操作,可以直接支持全局调转. 2.1<logic:present><l ...
- Heterogeneous System Architecture
https://en.wikipedia.org/wiki/Heterogeneous_System_Architecture Steps performed when offloading calc ...
- Nginx服务器
什么是Nginx? Nginx是一种服务器软件,如同apache.tomcat.是一种高性能的HTTP和反向代理服务器以及代理邮件服务器.也就是说Nginx服务器可以发布网站,也可以负载均衡,还可以作 ...
- 高德地图API应用
高德地图官网:http://api.amap.com/javascript/ 输入关键字,搜索地址功能的网页: 1.引用远程Map Api(js)网址形式(注册后获取) 2.定义个<div> ...
- Unicode与UTF8相互转化(使用MultiByteToWideChar)
1.简述 最近在发送网络请求时遇到了中文字符乱码的问题,在代码中调试字符正常,用抓包工具抓的包中文字符显示正常,就是发送到服务器就显示乱码了,那就要将客户端和服务器设置统一的编码(UTF-8),而我们 ...