Welcome

首页 / 软件开发 / C++ / 接触VC之四:COM组件模型基础

接触VC之四:COM组件模型基础2011-02-10释雪一年又一年,已经又过了一年了。我VC的生涯已经两岁了。可以相当地庆贺一下哟。回顾这一年的学习(唉,还没有工作实践呢。这年头,工作不好找哇。),还学了不少的好东西。其中,最重要的就是COM组件模型,我个人觉得这个几乎是Windows的核心。许多先进的技术(比如微软著名的DirectX,ADO,没有人会不知道吧)都以COM组件的形式发布的。现在,我瞄上了另一个好东东,就是泛型编程技术。它能够编写出清晰、灵活、高度可重用的代码,在ATL中就可以依稀看出它的影子(现在网上ATL文章有很多,我以后也会谈到它)。好了,关于泛型编程的事今后再谈。

按照我以前的计划,我应该谈谈我对COM组件模型的认识了。一来可以对自己的学习状况进行总结。二来,请教高手,可以帮忙指出错漏之处。三来,说不定会对初学者们有所帮助。请各位高手多多指正啊.在这里先谢了。

一、动态链接库:

动态链态库是大部分COM组件的承载对象(不要在意ocx,它同样也是dll,只不过改了一下后缀而已)。当然Exe同样也是可以的(TTS中的TextToSpeech对象就是一个例证),只不过在事实上要少得多。

在Windows初期,动态链态库的出现是一场革命。它改变了Windows的一生,也为当今Windows操作系统的霸主地位打下一块坚实的基石。(关于Windows的历史问题,我一直没有弄得太清楚。请VCKBASE的有关史学家们尽快写出一篇文章来吧^_^)。

微软对动态链接库就是这样解释的:

动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。

嗯,讲得很清楚。动态链接库首先是一个可执行文件(微软解释说,exe叫做起直接可执行文件),它里面包含着一组需要共享的函数。当使用时,动态链接库(和Windows系统)会提供一个方法来使我们的应用程序可以调用其中的函数。此外,动态链接库还会包含一些资源(如:图标、对话框模板等等)。在MFC中,微软在现有动态链接库的基础上施用了一些技巧来提供一些另外功能,如MFC类的导出。

动态链接库的链接方式大致分为两类: 静态链接和动态链接.

静态链接又叫隐式链接,这种链接方式使我们在代码中不用语句来指示系统中,我们的应用程序要加载哪些动态链接库。其静态链接声明是放在工程属性中的(或者使用#pragma comment(lib,"XXX.lib"),这个可以和#include放在一起)。在指定时,只需要输入其动态链接库相应的导入库文件(.lib)。然后,你就可以在程序的任何地方像调用普通函数一样调用该动态链接库中存在的函数了(当然,你需要包含其相应的头文件。一般情况下,头文件会和LIB文件一块给出)。通过这种方法生成的程序在运行初始化的时候(具体到什么时候不太清楚。但我可以肯定是在WinMain函数之前了^_^),会自动将动态链接库加载在系统环境中,并将其映射到我们应用程序的进程当中去。当我们调用一个我们进程没有定义的函数时,VC运行库会通过查找LIB文件的相关信息找到相应动态链接库的函数并调用它。进程结束时,系统会缷载动态链接库。

动态链接又叫显式链接,顾名思义这种方式让我们必需在代码通过调用API来显式地加载动态链接库。COM组件模型全部都是采用这种方式来加载进程内组件模块(就是Dll)的。(我觉得微软的专业术语有些混乱耶)。这个方式有许多好处,它可以在运行时决定具体要加载哪个链接库,要调用哪个函数…这才叫动态链接呢。

要使用动态链接库并不难,首先要调用LoadLibrary,其原型如下:

HMODULE LoadLibrary(
LPCTSTR lpFileName // file name of module
);

参数lpFileName是要加载的动态链接库的文件名。如果加载成功的话,就返回其句柄。否则的,返回NULL。

与这个API相配对的是FreeLibrary,其原型如下:

BOOL FreeLibrary(
HMODULE hModule // handle to DLL module
);

这个就不用我多说了吧。

当动态链接库被LoadLibrary所加载时,C运行库通过_DllMainCRTStartup来完成动态链接库的初始化,如全局对象(变量)、静态成员变量的生成以及赋初值。最重要的是它还会调用DllMain函数。每一个动态链接库都必须有这个函数,就像应用程序必须有main或WinMain一样。它的原型是:

BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
);