65.9K
CodeProject 正在变化。 阅读更多。
Home

COM 基础的友好方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (31投票s)

2002年11月3日

6分钟阅读

viewsIcon

115460

本文将帮助您以友好的方式入门COM基础知识。

引言

本文介绍了编程史上不断演进的COM的简单基础。我认为它对那些对这项技术一无所知的初学者来说很有用。至少我认为,这是简单友好的……

COM通过设计经典面向对象中最具商业价值的方面,以务实的方式解决了软件设计问题。如果您是Windows上的开发人员,那么就无法绕过对COM的了解。

COM的基本特性

  • COM是一个规范。它描述了为了创建组件您应该遵循的标准。
  • COM是面向对象的。每个COM对象都有自己的身份和状态。
  • COM对象是黑匣子。  
  • COM对象可以动态链接。只需将它们想象成计算机上的即插即用设备:插入即可开始工作。当您不再需要它时,将其拔出。
  • COM还使您能够创建分布式应用程序。调用COM对象时,您甚至不必知道它驻留在何处。它甚至可能驻留在远程计算机上的某个位置。
  • 可以使用任何支持函数指针的编程语言来编写COM应用程序。
  • COM组件是自版本化的。这意味着当您升级已有的COM组件时,它被视为同一组件的另一个版本。这样做是为了避免与旧客户端产生任何版本冲突。
  • COM组件有助于实现代码重用。一旦创建了COM组件,就可以在任意数量的项目中任意次使用它。

组件类型

  • 进程内 (In-process):它们以(DLL)动态链接库的形式存在。它们在客户端应用程序的内存空间中运行(因此称为进程内)。如果它们崩溃,它们会随着客户端应用程序一起崩溃,因为它们与客户端应用程序在同一内存空间中运行。
  • 进程外 (Out-process):它们以(EXE)可执行文件的形式存在。它们在与客户端应用程序不同的内存空间中运行(因此称为进程外)。如果它们崩溃,不会影响客户端应用程序,因为它们与客户端应用程序在不同的内存空间中运行。
  • 远程 (Remote):远程组件与其他组件一样,但唯一的区别是远程组件通过网络在单独的远程位置运行。它们使用DCOM(分布式COM)实现。

关于…的一点

COM组件具有唯一的身份标识号。这些号码存储在注册表中HKEY_CLASSES_ROOT主键下。如我在特性中所解释的,COM不仅仅是纸面上的规范。它还包括各种API。它还包含一些系统级代码。所有这些都存在于您的COM运行时库中。

组件对象库本身就是一个系统组件(通常存在于您的操作系统中),它使COM组件能够在进程内(in-process)、跨进程(out-process)或通过网络(remote)与其他组件进行调用。

您创建的组件对象是高度封装的。当您创建并分发一个组件时,使用它的客户端看不到实现代码。它甚至无法访问您放置代码的类。

如我之前解释过的,COM对象是黑匣子。尽管它们代表可重用组件,但重用性不像面向对象语言那样。COM对象可以包含其他COM对象,并将特定接口的实现委托给其他COM对象。但是,您不能像C++中从基类派生类那样,从现有对象派生一个对象。

如果这样,客户端如何使用您的组件来访问其中的服务?嗯,这时接口的概念就进来了。每个组件都有一个它必须实现的接口。该接口不包含任何方法的实现:这些实现在Co-Class(组件类)中。接口仅包含方法声明。接口是客户端访问组件服务的唯一方式。

现在,接口是使用VTable实现的。VTable包含一个指针数组。这些指针又指向组件的函数。当您在代码中创建组件对象时,它也会在内存中创建其VTable

所有COM对象都实现一个特定的接口IUnknown。通过此接口,可以获得有关COM对象可能支持的其他接口的信息。

客户端创建指向接口的指针。该指针指向一个虚拟指针。虚拟指针指向VTable。使用接口指针和虚拟指针,组件的客户端可以调用其中的任何函数。

接口主要有两种类型

  • 标准接口 (Standard Interfaces):这些是COM库提供的接口。一些标准接口包括IUnknownIDispatchIClassFactoryIOleIDataObjectIStreamIStorage
  • 自定义接口 (Custom Interfaces):这些是您创建的接口。

组件的标识

随着组件在全球范围内开发和使用,我们必须唯一地标识每个组件。那么,您认为这如何实现呢?嗯,开放软件基金会(OSF)挺身而出,开发了一种生成唯一标识符(称为UUID(通用唯一标识符))的算法。在COM中,它被称为GUID(全局唯一标识符)。GUID是分配给接口、类或库的数字。

COM对象通过GUID(全局唯一接口标识符)进行标识。它们是128位数字,具有统计学上的唯一性;程序员无需担心其他人使用通过为此目的提供的工具或函数生成的相同GUID。

我们不会深入探讨该算法的工作原理,但让我告诉您它在生成唯一标识符时所考虑的方面

  • 当前日期和时间
  • 网卡地址
  • 系统时钟
  • 自动递增计数器

现在,每个COM对象都有一个唯一的GUID,但是所有这些GUID都存储在哪里?它们存储在您的注册表中。所有COM类都注册在HKEY_CLASSES_ROOT\CLSID键下。对于每个CLSID键,还有一个名为InProcServer32的子键。该子键的值将是与相应类关联的DLL的文件名。

每当您创建一个组件时,它将是EXE或DLL的形式。您必须在将要使用它们的计算机上注册它们。如果您分发组件,它可以是安装过程的一部分,自动完成,对用户不可见。您也可以手动完成。

可以使用以下命令注册DLL(动态链接库)

在命令行中

REGSVR32 <name of Your COM DLL >

可以使用以下命令注册EXE(可执行文件)

<COM exe name > /REGSERVER

在本文中,我试图在一定程度上解释COM的基础知识和基本原理。如果您有任何建议(无论是积极的还是消极的),请随时与我联系。

© . All rights reserved.