MFC所依赖的动态库--MFC是如何创建出来的

1.Dependency Walker的第一道揭秘

在MFC中我们写过很多静态库和动态库。这些dll都依赖于MFC;然后我们又交给别人使用,使得它们被依赖。

细想一下,就可能会发现其中的不平衡。我们生成的非组件dll,要交给别人使用,必须提供h头、lib库和dll库文件;可是我们使用MFC的dll时,好像什么也没有设置,MFC不请自来的加入到我们的程序中。虽然知道这个世界,每个人其实并不是平等的;但是在计算机的世界,自由平等却是第一法则。搞清MFC如何嵌入到我们的应用程序中,将一切黑暗中的操作暴露出来,将是我们的任务。

举个例子,随便用向导生成一个MFC 的对话框程序。里面测试一个组件,然后调用wcslen求一个BSTR的长度。就是一个很简单的exe;通过Dependency Walker就发现它依赖了很多dll。如下:

 其中,这些函数何去何来,这个就是我们要弄清楚的秘密。

  • MFC42D.DLL
  • MSVCRTD.DLL
  • MFCO42D.DLL
  • OLEAUT32.DLL
2.MFC的组成

直接揭开谜底:MFC由四部分组成。可能这种说法不准确,应该说,VC的核心底层API由下面部分组成:

  • CRT(C runtime): 最底层的微软对c、c++标准库的实现版本;接口参照标准规范;MFC依赖于此。但是windows API不依赖于此,有内部自己的实现版本
  • Windows API: 微软的操作系统怎么弄出来的,全靠它们了,以C的API形式提供
  • MFC: 对windows API进行类的封装。基本上涵盖部分CRT和全部Windows API。该小组是AFX小组。
  • ATL: 微软全面迈入组件解决方案时的封装。该小组是Com小组。

如下表:


其实看看vc的目录组织结构大概也知道其分组。


MFC 静态库和动态库

最流行的是使用MFC作为dll,同时将自身的也作为dll。在这种情况下,如果深挖进去,最容易发现的是MFC的dll。

参照 MSDN中的“Naming Conventions for MFC DLLs”,可以发现,基于动态链接库的MFC的命名规范为:MFC[D|O|N]x[U][D].DLL。

主要包含的属性为:功能模块(Core | OLE | DB | NET),版本(VC6对应42,VS2003对应70,VS2005对应80,VS2008对应90),是unicode还是Ansi,是release还是debug。

稍微注意的是:debug版本下每个功能模块对应一个lib;但是release版本下,合起来为一个统一的lib文件MFC42.lib。

其实还存在,静态链接库。但是其名字可能更不着调 :[N|U]AFXDW[D].LIB

其中包含unicode和非unicode,debug和release区分。

CRT 静态库和动态库

参照MSDN中的“INFO: What Are the C/C++ Libraries My Program Would Link With?”。

当我们调用sprintf,wcslen等此类函数时,我们就依赖了该库。

这个可以通过编译设置:



实际上对应的编译项是:/MD /ML /MT


3.静态库和动态库
核心

有关静态库和动态库的相关概念,以及连接中出现的一些问题,其实所有的核心就是:

  • 搞清楚引用别人的库是静态还是动态库;
  • 把自己作为库给别人使用时是静态库还是动态库

真正所谓取之与民,用之于民。

其中还经常出现的一个问题是,引用的系统底层库有哪些,到底是静态库还是动态库。通常,对于MFC程序,一定会依赖于MFC库;可以选择性的依赖CRT库。搞清楚使用的静态库和动态库,不要冲突就行。

几种静态库和动态库

在VC6中,对于静态动态库,去除组件作为一种特殊的动态库外,还剩下5种类型。一一生成一个演示程序,研究设置,大概就可以看出区别。

静态库导出的是 h头文件和lib文件。该lib文件包含着程序代码,会比较大。源代码编译的时候使用头文件,链接的时候使用lib文件。

动态库导出的是 h头文件、lib和dll文件。该lib文件只包含着程序的函数索引位置,比较小。源代码编译时使用头文件,链接时使用lib文件,运行时需要dll文件。


这是MFC dll



 以下是对各dll分析:



其实,本质上可以看出,只有两种库:静态库和动态库;标明自身是静态库还是动态库。

静态库由于生来是被别人使用的,所以也就不存在导入导出标识;

而动态库一定要存在导入导出标识。对于dll,存在MFC dll和普通的win dll。其实所谓的MFC dll只不过是将DllMain进行特殊封装,特别是为了方便资源的存取。而所谓的Extension dll,只不过是为了兼容C;要求只导出非MFC类的函数而已。

这些静态库如何使用MFC 库,如何使用CRT库,其实都是可以设置的。这点用来解决引用库是什么库。

对于静态库和动态库,MFC向导生成时,会自动弄出一些编译设置项。但是最根本的核心还是dsp中的:

# TARGTYPE "Win32 (x86) Static Library" 0x0104

!MESSAGE "TestStaticLib - Win32 Release" (based on "Win32 (x86) Static Library")

!MESSAGE "TestStaticLib - Win32 Debug" (based on "Win32 (x86) Static Library")

如果要将一个静态库编译成另一个动态库,或者相反;只需要在dsp中统一查找替换为另一种格式即可。当然,更加鼓励的是生成多个编译配置项。

避免冲突的方法

对于静态库和动态库,在编译链接中总是会存在问题。这些问题的根本原因在于:一个工程中,同时对于某一个工程,既引入了其静态库,又引入了其动态库。这样会出现同名冲突。

  • 解决的方法有两种:
  • 确保所有工程对某个库采用同一种方式引入。这个可能要搜遍所有工程
  • 对于编译不过的工程,已知某一个库冲突,将该库的静态和动态库忽略一个即可。

4.如何最大化最合理利用各功能库
  • 程序如果就是一个MFC程序,建议尽量使用MFC库;尽量不依赖于CRT库。
  • 程序如果只是一个WIN32 程序,建议尽量不使用MFC库,选择性的依赖于CRT库。
  • 程序如果只是一个控制台程序,尽量依赖于CRT库,少依赖于win api库和MFC库。

原则,尽量少的依赖库。对于同功能的函数,可能CRT有,Win API库,MFC库,选择性的找到正确的库。






  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值