COM对象创建过程

在客户端需要调用COM组件时,通常调用windowAPI函数:

STDAPI CoCreateInstance(
REFCLSID rclsid, //创建的Com对象的类标识符(CLSID)
LPUNKNOWN pUnkOuter, //指向接口IUnknown的指针
DWORD dwClsContext, //运行可执行代码的上下文
REFIID riid, //创建的Com对象的接口标识符
LPVOID * ppv //用来接收指向Com对象接口地址的指针变量
);
来返回所需函数的接口ppv。其实这个函数是一个封装函数,共封装了创建COM对象的两个步骤。
 
一、类工厂
类工厂(IClassFactory),是用来生成类对象实例(即给类分配内存)并返回所请求接口(上面的ppv参数)的一个类。
COM组件中的类与类工厂是分离的。从本质上讲,类工厂类生育了我们所需要的那个类。
如何办到的呢?
类工厂有个函数 HRESULT CreateInstance(LPUNKNOWN pUnk,REFIID riid,void** ppv),该函数传入所需要的类的那个接口的IID(riid),并返回那个接口ppv.
在这个函数内部,所需类是通过new函数直接创建的,然后调用这个类的QuryInterface()函数返回那个接口ppv的。
因此,最终类还是通过new函数创建的,只是把这个过程隐藏了,不对客户公开。
二、DllGetClassObject函数
该函数用来创建类工厂实例,并返回类工厂接口指针。通过这个指针调用CreateInstance()就实现了获取所需接口的指针。
STDAPI DllGetClassObject(REFCLSID rclsid,REFIID riid, LPOVID* ppv)
rclsid:组件的GUID
riid:类工厂的GUID
ppv:类工厂的接口指针
因此总的顺序就是:
CoCreateInstance调用CoGetClassObject()加载COM组件,后者调用DllGetClassObject(clsid,id_ifactory,ppv_factory)生成类工厂指针,类工厂指针再调用CreateInstance()生成类实例,返回接口指针。
 
至于为什么要通过类工厂创建组件对象实例,原因有二:
1.类工厂创建对象是对对象创建过程的一种统一封装,实现不同语言创建COM组件统一性。
2.COM对象可以位于客户进程之外。
 
至于接口和类之间是怎样一一映射的,可能是通过他们的GUID建立起来的映射关系。因为类也有自己的GUID,因此类工厂只提供了接口的GUID,但是还是能够实例化接口对应的类。
原文地址:https://www.cnblogs.com/zhuluqing/p/8561267.html