最近在读潘老师写的COM原理与应用,收获颇丰。自己把这些收获记录下来,一方面是为了分享,一方面是为了将来自己回顾。自己看书最大特点是喜欢总结,但最大的失败是往往过后就会忘记这些总结。所以开通博客,记录于此。
COM组件、COM客户程序、COM库,三者构成了COM应用的结构。客户程序通过COM库来调用COM组件。具体就是首先通过regsvr32.exe注册COM组件,将COM信息包括COM组件的路径,类型等等写入到注册表中。
然后客户程序通过调用COM库的CoGetClassObject函数获得组件类厂对象的接口。CoGetClassObject函数的内部实现机制是通过GUID从注册表中找到组件的路径,将组件载入到内存中,并调用组件的导出函数DllGetClassObject,这个导出函数中会创建类厂对象,并将类厂的接口指针返回给客户端。
客户端调用类厂的函数CreateInstance来创建COM对象,并返回COM对象接口指针。COM库提供了函数CoCreateInstance可以直接创建COM对象。通过COM对象的QueryInterface接口来获得COM对象支持的各个接口指针。最后通过这些接口指针来访问接口中的函数。COM对象中的各个接口具有不同的GUID,通过传递不同的GUID来调用QueryInterface,实现COM对象的接口跳转。
现在来说下COM组件中的包容和聚合。假设组件A具有接口SomeInterface,要实现一个组件B,使B具有SomeInterface接口功能,以及OtherInterface接口功能。那么接口B可以通过两组途径来继承A的接口功能:包容和聚合
包容:B同时向客户程序提供SomeInterface接口和OtherInterface接口功能。组件B在类厂的CreateInstance函数中创建对象B后,应当再创建一个对象A,将A的SomeInterface接口指针保存下来,当客户调用B的SomeInterface接口时,B的SomeInterface接口只有函数的说明,具体的功能实现在对象A的SomeInterface接口中。因此B的接口中函数负责转发,调用对象A的SomeInterface接口中相应的函数。
聚合:B只提供OtherInterface接口,不提供SomeInterface接口,当客户程序访问SomeInterface接口时,B将A的SomeInterface接口指针提供给客户程序,客户程序通过A的SomeInterface接口指针来访问。为了保证COM一致性,机通过不同接口得到IUnknown接口指针应该一致。因此还要改写组件A,在组件A中接口跳转可以调到B的IUnknown接口,而不是A的IUnknown接口。
包容和聚合异同:
需不需要在对象B中添加SomeInterface接口,并增加该接口中所有函数的说明
需不需要改写组件A
包容和聚合都是为了实现组件的重用。
自己刚看完书,总结的有点混乱。以后再慢慢完善吧。下面是包容和聚合图