“COM库”详解

“COM库”的意思是,为了支持COM功能实现,需要这个COM库,它在COM 客户,服务器之外扮演第三个角色。其实可以理解为一套DLL。COM基本功能的实现经常会需要调用COM库的引出函数。

     
一 类厂的概念
       类厂是COM对象的生产基地,COM库通过类厂创建COM对象。所以确切的讲,类厂应该称为“对象厂”。类厂本身也是一个COM对象,支持一个特殊的接口IClassFactory。 厂其c++表示如下:
      class IClassFactory: public IUnknown
      {
        virtual HRESULT _stdcall CreateInstance
        ( IUnknown * pUnknownOuter,   /*IUnknown * pUnknownOuter 参数只用于对象类聚和的情况,其他时候都为NULL*/
          const IID&iid,   /*const IID& iid 参数为对象创建成功后传递给客户的初始接口的IId*/
          void **ppv    /*void ** ppv存放返回的接口指针。 */
        )=0 ;
        virtual HRESULT _stdcall LockServer (BOOL bLock)=0 ; /*成员函数LockServer()用于控制组建的生存周期*/
//
      }
      对应于每一个com类都应该用一个类厂专门来对该类的对象进行创建。 这个创建操作就通过其成员函数 CreateInstance完成。 因为每个类场只对应一个特定的COM进行创建对象,所以类厂CreateInstance函数会知道该如何创建。该函数各个参数的含义如标注所示。
      类厂创建对应的COM类的对象;而COM组件中的类厂是由 HRESULT DllGetClassObject() 引出函数创建。请注意,这个引出函数是定义在服务器端的组件dll中。而这个函数对于客户来说是透明的,也就是说,客户不会直接调用这个函数。
      HRESULT DllGetClassObject
      (
        const CLSID& clsid,
        /* const CLSID& clsid是待创建对象的CLSID*/
        const IID& iid,
        /*const IID& iid表示指定接口IID;*/
        (void **) ppv
        /*void ** ppv 存放类厂接口指针。*/
      ) ;
      标准COM库在接到对象创建的指令后,调用进程内组件的DllGetClassObject函数创建类厂对象,并返回类厂对象的借口指针。 然后客户就可以通过类厂对象的CreateInstance()函数和篡改相应的COM对象。下面详细介绍这个过程。
二 COM库与类厂的交互
      类厂是由函数:DllGetClassObject()函数创建。而类厂的创建过程对客户程序来说是透明的,也就是说客户并不知道类厂的存在。
      在标准COM库中,有三个API函数可以用于COM对象的创建:CoGetClassObject(), CoCreateInstance(), CoCreateInstanceEx()。客户可以调用其中之一来创建对象并获得新对象的初始接口指针。而COM库与类厂也通过这三个函数进行交互。其实在这些函数中,调用了服务器端组件的DllGetClassObject()函数来创建了类厂对象。分别介绍这三个函数。
     1 HRESULT CoGetClassObject
      (
        const CLSID& clsid,
       
        DWORD dwClsContext, /*指定组件类型:进程内,进程外,进程内控制对象(类似于进程外组件的代理对象,用于ole技术)*/
        COSERVERINFO * pServerInfo, /*在创建远程对象时指定服务器信息,其他时候设置为NULL*/
        const IID& iid,   /*对应DllGetClassObject() 函数的 iid参数,指定接口IID 。通常为IClassFactory的接口标志符
                                 IID_IClassFactory,也可以为IClassFactory2的接口标志符。*/
        (void **)ppv /*对应DllGetClassObject() 函数的 ppv参数,存放类厂对象的接口指针*/
      );
      如果COM对象是进程内组件对象则 CoGetClassObject()调用DLL模块的DllGetClassObject引出函数来创建类厂,并返回类厂对象接口指针。
       如果CoGetClassObject()函数创建的类厂对象位于进程外组件,则进行一下步骤:(1)CoGetClassObject()函数启动组件进程,(2)等待组件进程把它支持的COM类对象的类厂通过函数CoRegisterClassObject()注册到COM中,以便COM库创建COM 对象使用 (3)CoGetClassObject函数把COM相应的类厂信息返回 (4)当组件进程退出时,调用CoRevokeClassObject()函数使得类厂对象不再有效。组件程序调用CoRegisterClassObject()和CoRevokeObject()必须成对调用。
    
      2 不过在在通常的com对象创建过程中,客户端不会直接调用CoGetClassObject() 函数创建并获得类厂对象并获得接口指针,而是调用函数CoCreateInstance()。这样客户可以通过一次调用就获得最终的COM对象,类厂的创建对客户是完全透明。函数CoCreateInstance定义如下以及实现如下:
        HRESULT CoCreateInstance
        (
          const CLSID& clsid,
          DWORD dwClsContext, /*指定创建类型:进程内,进程外,进程内控制对象*/
          const IID& iid, /*对应DllGetClassObject() 函数的 iid参数,指定接口IID 。通常为IClassFactory的接口标志符
                                 IID_IClassFactory,也可以为IClassFactory2的接口标志符。*/
          (void **) ppv /*对应DllGetClassObject() 函数的 ppv参数,存放类厂对象的接口指针*/
         )
        {
          IClassFactory *pCF;
          HRESULT hr;
          hr=CoGetClassObject(clsid, dwClsContext, NULL, IID_IClassFactory, (void *)pCF) ;
            /*首先创建类厂对象,并获得类厂对象接口指针。注意 COSERVERINFO * pServerInfo参数为NULL,因此无法这个函数不适用于创建远程机器上的对象*/
          if (FAILD(hr))
             return hr;
          hr=pCF->CreateInstance(pUnkOuter, iid, (void *)ppv) ;
            /*由获得的类厂对象接口指针创建对应COM对象实例*/
          pCF->Release() ; //注意这句,类厂对象在创建完自己的COM对象就丢弃了。
         
          return hr;
        }
        这个函数的功能就是把类厂创建对象的过程封装起来。这样客户只要指定对象类的CLSID和要输出的接口指针及接口ID,函数返回后客户就可以得到对象的接口指针。    
      3因为函数CoCreateInstance()无法创建远程机器上的COM对象,因此还需要另一个函数:CoCreateInstanceEx()。这个函数唯一特别的地方在于其使用了PSERVERINFO * pServerInfo参数。其函数声明如下:
       HRESULT CoCreateInstanceEx
       (
        const CLSID& clsid,
        IUnknown* pUnknownOuter, /*适合聚合,一般为NULL*/
        DWORD dwClsContext, /*创建的对象类型:进程内,进程外,进程内控制对象*/
   COSERVERINFO * pServerInfo, /*创建远程机器上对象时指定远程机器信息*/
        DWORD dwCount, 
        MULTI_QI* rgMultiQI
      ) ;
  参数pServerInfo指定服务器信息, DWORD dwCount 与参数 MULTI_QI* rgMultiQi 指定了一个结构数组,可以保存多个对象接口指针,这样可以一次获得多个接口指针,节省网络交互。
     
      一般来说, 如果创建远程对象或者希望一次获取对象的多个接口,则选用CoCreateInstanceEx()API函数; 如果希望获取类厂对象或者调用类厂的成员函数则选用CoGetClassObject()API函数; 其他就是最常用的情况,用CoCreateInstance()API函数来创建COM对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值