概述] 本文从基本的概念入手,在COM的接口,类型库,GUID,等方面清楚的展示了COM。同时本文还介绍了COM对象的创建,什么是MTS,如何利用MTS管理COM对象,他的优点和编程实现,并结合了具体的实例,本文的另一重点是介绍COM在互联网上的应用,通过安全性,效率等比较说明,展示了COM在互联网上的强大的应用前景。在论述的过程中,本文结合了C++,VB和ASP来说明。
[SUMMARIZE] In this article,the author introduce the technology of COM.From the interface,the type library and GUID Clearly show the character of COM.This article also list how to create COM object,how to Using MTS to manage the COM object,And how to make MTS in program.AS another emphasis,The article demonstrate the application of COM in internet,through the analysis of security and efficiency,show the power of COM.
关键字:COM,MTS,组件技术
前言
在互联网发展到了今天,网络环境下的编程标准有很多,COM是其中之一,也是发展最快,应用面最广的标准。但目前在国内,没有多少真正介绍COM的书,加上COM本身理解起来也有难度,推广和使用COM比较困难,本文试图从概念和应用结合的角度,把COM展示给读者。并介绍了COM在Internet上的应用。
一。Com技术概论
COM(Component Object Model)微软的组件对象模型.它的实质是一些小的二进制可执行的程序,它可以为应用程序和操作系统以及其他的组件提供服务.微软的许多其他的技术如:ActiveX,DirectX,OLE等都是基于COM建立的.
COM的发布形式是:以win32动态链接库(DLL)或者以可执行文件(EXE)的形式发布的可执行代码组成。 其中以DLL形式发布的方式实现的组件程序,在客户调用时会把组件程序和客户程序运行在同一个进程中,所以被称为进程内的组件。以EXE的形式发布,在客户调用时,他有自己的独立的进程空间。故称为进程外的组件。
COM也不是win API那样的一个函数集:它并没有支持或者提供各种函数来对系统进行特定的操作。COM本身要实现一个称为COM库(COM library)的API,它提供诸如客户对组件的查询,以及组件的注册/反注册等一系列服务,一般来说,COM库由操作系统加以实现,程序员不必关心其实现的细节。
总体来看,COM提供了编写组件的一个标准方法。遵循COM标准的组件可以被组合起来以形成应用程序。至于这些组件是谁编写的,是如何实现的并不重要。组件和客户之间通过"接口"来发生联系。
1.COM接口是一组逻辑上相互关联的操作,这些操作定义了某种行为,也就是这组操作的规范,而非特定的实现,实质也就是接口代表了接口调用者和实现者之间的一种约定.接口的理解是非常重要的,因为所有的对COM的操作都是通过接口指针来进行的.通过接口我们把组件的功能展示给了调用者(ASP Pages等)
每个COM接口都提供一个名叫IunKnow接口,该接口包括了ADDREF(),RELEASE(),和QUERYINTERFACE()三个接口,前两个接口是用来操纵对象引用计数,因为每个COM对象的创建都需要消耗系统的资源,引入了这两个函数后,当对象被创建或其他用户将一个指针指向该对象时,调用ADDREF()方法,将引用计数加一,当不再使用该对象时,调用RELEASE()方法,将引用计数减一,当计数为0时,对象释放自己,就可以避免每次引用对象时都重新创建,使资源可以合理的分配使用。QUERYINTERFACE()接口是用来查寻该对象是否用来支持其他的接口的,您需要传递欲查寻的接口的IID以及一个指向输出参数的指针。每个COM接口都是从IunKnow接口派生出来的,在其VTBL中的开始的三个条目就是指向上述三个函数的指针。下面写出这三个接口的实现方法:
/* 引用对象*/
ULONG IUnKnown::AddRef(void)
{
m_RefCount++; /*引用计数加一*/
return m_RefCount; /* 返回当前的被引用次数的总数 */
}
/*释放对象的*/
ULONG Iunknow::Release(void)
{
m_RefCount--; /* 引用次数减一 */
if (m_RefCount==0) /* 如果计数值为0,对象释放自己 */
{
delete this;
return 0;
}
return m_RefCount; /* 返回当前的被引用次数的总数 */}
/*查询接口*/
HRESULT IunKnow::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
if(riid==IID_IUnknown || riid==IID_IDropTarget) /*检查是否对象支持所查询的接口*/
{
ppv=(LPVOID) this; /* 把被请求接口的指针赋给输出参数 */
AddRef(); /* 引用对象 */
Return S_OK; file://成功的标记
}
else{
*ppv=NULL; /* 把输出参数的指针赋为空 */
return E_NOINTERFACE; /* 返回失败的信息 */
}
}
VB实现的COM很多细节都是VB自动完成的,用户只是定义各个方法的实现部分,其它的工作全部交给系统处理,而在VC和Delphi中接口的声明和实现都要用户来实现,用户就可以自由的控制一些低层的东西。
2. 类型库:类型库是一个描述信息的集合,这些描述信息涉及组件的类、接口及接口上的方法以及这些方法的参数类型。类型库通过ITYPELIB接口来访问,对于VB等智能开发环境,无法使用C++头文件来找到接口的方法和属性的信息,这时可以把类型库当做独立于语言的头文件,用他可以轻松的解决如用户界面等问题,使程序开发更加的简单。
3.GUID:又称为全局唯一标识,用于唯一的区分COM中的条目的标识。GUID的结构定义如下: typedef struct_GUID { unsigned long Data1;
unsigned long Data2;
unsigned long Data3;
unsigned long Data4[8];
}GUID;
生成GUID来标识对象类或接口。它共有128位,在理论上不存在GUID间的冲突。在运行阶段,程序可以 通过API函数CoCreateGuid()来完成,而在开发阶段,可以通过运行应用程序:GUIDGEN.EXE来获得。在COM中有三个GUID:CLSID(标识类对象),ProgID(标识类易称)和IID(标识接口),其中的ProID和CLSID一一对应,因为ProID比较容易记忆和识别,在VB等智能开发环境里,基本上都用ProID,但在具体实现时,VB等却还是要先运行CLSIDFromProID函数来得到对象的的CLSID,再调用CoCreateInstance函数来创建COM对象.
最后介绍COM对象的创建:客户程序通过函数CoCreateInstance()创建对象(指定需要的CLSID和接口),在程序里通过CLSID标识要创建的对象,COM使用该CLSID在注册表里找到服务器的位置,然后创建对象。在VB里有两种创建对象的方法:1。new <某个对象> 它实际上还是在调用Co