天天看点

C++ COM编程-COM编程入门实践

1. COM编程基础

COM是一种规范,而不是实现。

当使用C++来实现时,COM组件就是一个C++类,而COM接口就是继承至IUnknown的纯虚类,COM组件就是实现相应COM接口的C++类。

COM规范规定,任何组件或接口都必须从IUnknown接口中继承而来。IUnknown定义了3个重要函数,分别是QueryInterface、AddRef和Release。其中,QueryInterface负责组件对象上的接口查询,AddRef用于增加引用计数,Release用于减少引用计数。引用计数是COM中的一个非常重要的概念,它很好地解决了组件对象地生命周期问题,即COM组件何时被销毁,以及谁来销毁地问题。

除了IUnknown接口外,还有另外一个重要地接口,即IClassFactory。COM组件实际上是一个C++类,对于组件地外部使用者来说,这个类名一般不可知,那么如何创建这个类地的例?由谁来创建?COM规范规定,每个组件都必须实现一个与之对应的类工厂(Class Factory)。类工厂也是一个COM组件,它实现了IClassFactory接口。在IClassFactory的接口函数CreateInstance中,才能使用new操作生成一个COM组件类对象实例。

COM组件有3种类型:

① 进程内组件(CLSCTX_INPROC_SERVER)

② 本地进程组件(CLSCTX_LOCAL_SERVER)

③ 远程组件(CLSCTX_REMOTE_SERVER)

在接口成员函数中,字符串变量必须用Unicode字符指针,这是COM规范的要求。

2. COM组件开发

实现一个COM组件,需要完成以下工作:

COM组件接口

COM组件实现类

COM组件创建工厂

COM组件注册与取消注册

本文以一个例子作为说明,COM组件提供了一个SayHello的接口函数,将“Hello COM”打印输出。

2.1 创建COM组件接口

COM组件接口是一个继承IUnknown的抽象类:

COM组件类是一个实现了相应COM组件接口的C++类,注意:一个COM组件可以同时实现多个COM接口。

2.3 COM组件创建工厂

对于组件地外部使用者来说,这个COM组件的类名一般不可知,那么如何创建这个类地实例?由谁来创建?COM规范规定,每个组件都必须实现一个与之对应的类工厂(Class Factory)。类工厂也是一个COM组件,它实现了IClassFactory接口。在IClassFactory的接口函数CreateInstance中,才能使用new操作生成一个COM组件类对象实例。

2.4 COM组件的注册

COM组件需要使用regsvr32工具注册到系统才能被调用,然而COM组件是如何被regsvr32注册的?一个典型的自注册COM组件需要提供4个必需的导出函数:

DllGetClassObject:用于获得类工厂指针

DllCanUnloadNow:系统空闲时会调用这个函数,以确定是否可以卸载COM组件

DllRegisterServer:将COM组件注册到注册表中

DllUnregisterServer:删除注册表中的COM组件的注册信息

DLL还有一个可选的入口函数DllMain,可用于初始化和释放全局变量

DllMain:DLL的入口函数,在LoadLibrary和FreeLibrary时都会调用

导出文件(Source.def):

生成完后,使用regsvr32注册到系统中:

3. COM组件使用

COM组件的使用包括:

如何创建COM组件

如何得到组件对象上的接口以及如何调用接口方法

如何管理组件对象(需熟悉COM的引用计数机制)

下面的代码是最一般的步骤:

下面我们编写一个客户端,调用之前写的COM组件服务:

上面的例子和一般步骤不一致,少了QueryInterface,是因为默认返回的就是指定的接口,下面按一般步骤再实现一次:

是直接创建COM组件并获取接口,还是先创建COM组件得到默认接口再查询其他的接口,需要具体问题具体分析。

4.COM组件运行机制

一个COM组件从编写到最终可以被调用,整个运行流程是怎样的?或者我们再考虑简单一点,COM组件是如何被调用的?

继续阅读