2007年7月26日星期四

ATL8的COM服务器实现(一)

在现阶段,ATL仍然是实现COM组件的一个重要手段。在几年的发展中,ATL出现了两个重要的版本-ATL3和ATL8。虽然ATL8已经出来好几年,但是由于我一直重用着以前用ATL3开发的老代码,因此对ATL8没有什么太多的研究。这次借着新项目的机会,能够正式使用到Visual Studio 8进行开发,我也因此得以好好的研究了一下ATL8的实现。虽然现在是.net大行其道的时代,但我这个守旧的人还是希望能记录下这个快要被遗忘的技术的研究心得。


COM服务器的种类

Win32版本的COM有两种服务器

  • inporc server --进程中服务器(动态链接库,DLL等形式)
  • out-of-proc server --进程外服务器(exe程序,进程外是对客户进程而言)
其中out-of-proc server有几个特例,一个是DCOM,可以叫做Remote Server,一种是系统服务,也就是service。

对于InProc-Server,我没有过多的研究其在ATL8中的实现,毕竟相当简单。这里主要对out-of-proc Server的实现进行研究。研究对象也是一般的EXE程序,而不是service。

COM服务器的职责

COM服务器有三个基本职责
  • 注册和反注册服务器
  • 暴露类厂(实现IClassFactory),使SCM能够访问
  • 服务器生命周期管理
进程外服务器简述

进程外服务器就是一个exe程序。如果在命令行上面指定 regserver或unregserver就能要求该服务器进行注册和反注册。注册成功就会在注册表中出现该服务器所包含的所有接口的ProgID和ClSID。ATL实现了这个简单的功能。

ATL同样是调用标准COM辅助函数CoRegisterClassObject把类厂和每个类的IUnknown暴露给SCM,这样客户就可以通过SCM来使用组件提供的接口。在Server结束生命周期之前,调用
CoRevokeClassObject把组件从SCM中注销。

对于生命周期管理,由于是exe程序,所以它可以自己管理自己的生命周期。当服务器检测到已经没有任何客户在引用它内部对象时,它可以选择是否退出运行(ATL中默认是exe退出运行)。


服务器与COM对象

一个服务器在程序中是什么呢?事实上没有具体的对象可以代表它。ATL使用OO编程,因此为服务器定义了一个类,其最高层父类是CAtlModule。它是个全局变量,因此它有着和exe程序本身相同的生命周期,因此由他管理COM对象再合理不过。

一个COM对象可以通过CoCreateInstance创建。它有自己的类厂,该类厂实现IClassFactory接口。
注:有些对象是不能被CoCreateInstance创建的,只能通过其他对象间接的创建。

那么服务器如何与COM对象打交道呢?
ATL从一开始的版本就提供了一个叫Object Map的结构来存放服务器内COM对象的信息。CAtlModule(简单起见,就把它当作服务器吧,这样容易理解一点)利用Object Map来做要求每个类自己注册和反注册,创建类厂,提供一些辅助函数来进行初始化和结束前的工作。

下一章 详细介绍Object Map




没有评论: