Inside COM读书笔记类厂

 1.CoCreateInstance


     通过传人参数CLSID创建相应组件的一个实例,并返回此组件实例的某个接口。
  •      CoCreateInstance的声明
      HRESULT  __stdcall  CoCreateInstance(
      __in REFCLSID rclsid,
      __in_opt LPUNKNOWN pUnkOuter,
      __in DWORD dwClsContext,
      __in REFIID riid,
      __deref_out LPVOID FAR* ppv
      );
     有四个输入参数和一个输出参数,第一个参数待创建组件的CLSID,第二个参数用于聚合组件,第三个参数是限定所创建组件的执行上下文。第三个参数组件上待使用的接口IID,最后一个参数返回接口的指针。
  •      CoCreateInstance的使用
      //Create Component
IX *pIX = NULL;
HRESULT hr = CoCreateInstance(CLSID_Component,
                                    NULL,
                                    CLSCTX_INPROC_SERVER,
                                    IID_IX,
                                    (  void **)&pIX);
if (SUCCEEDED(hr))
{
      pIX->Fx();
      pIX->Release();
}
   

  类上下文


     CoCreatInstance第三个参数dwClsContext可以控制所创建的组件是在与客户相同的进程中允许,还是在不同的进程中运行,或者是子啊远程机器上运行。


     客户可以在三种不同的上下文中使用某个组件:进程中、本地以及远程。常用组合定义:


2.类厂


     CoCreateInstance实际上并没有直接创建COM组件,而是创建一个被称作类厂的组件,再由类厂创建组件,起唯一功能呢就是创建其他的组件。精确的说是某个特定的类厂将创建只同某个特定的CLSID相应的组件。客户可以通过类厂所支持的接口来对类厂创建组件的过程加以控制。创建组件的标准接口是
IClassFactory。
     CoGetClassObject
     CoCreate接收一个CLSID作为参数并返回指向所创建的组件中的某个接口指针。为创建同某个组件想对应的类厂,需要CoGetClassObject函数。
HRESULT  __stdcall  CoGetClassObject(
      __in REFCLSID rclsid,
      __in DWORD dwClsContext,
      __in_opt LPVOID pvReserved,
      __in REFIID riid,
      __deref_out LPVOID FAR* ppv);

参数和CoCreateInstance很相似。第一个参数都是组件的CLSID.第二个参数则是创建组件的执行上下文。最后两个参数也想同,CoGetClassObject返回的是指向类厂中某个接口的指针。而CoCreateInstance是返回的指向组件中某个接口的指针。其中pServerInfo指针将被DCOM用于控制对远程组件的访问。
     ICalssFactory
       IClassFactory :  public  IUnknown
    {
     public :
         virtual  /* [local] */  HRESULT STDMETHODCALLTYPE CreateInstance(
             /* [unique][in] */  IUnknown *pUnkOuter,
             /* [in] */  REFIID riid,
             /* [iid_is][out] */  void  **ppvObject) = 0;
       
         virtual  /* [local] */  HRESULT STDMETHODCALLTYPE LockServer(
             /* [in] */  BOOL fLock) = 0;
    };
       
     CoCreateInstance与CoGetClassObject的比较
     在每次创建组件时,先创建相应的类厂,然后获取IClassFactory指针来创建所需接口比直接调用CoCreateInstance来创建所需的组件要复杂。看下如何用CoGetClassObject实现CoCreateInstance:
     HRESULT  __stdcall  CoCreateInstance(
      __in REFCLSID rclsid,
      __in_opt LPUNKNOWN pUnkOuter,
      __in DWORD dwClsContext,
      __in REFIID riid,
      __deref_out LPVOID FAR* ppv)
{
      *ppv = NULL;
      IClassFactory *pIFactory = NULL;
      HRESULT hr = CoGetClassObject(rclsid,
            dwClsContext,
            NULL,
            IID_IClassFactory,
            (  void **)&pIFactory);
        if  (SUCCEEDED(hr))
      {
            hr = pIFactory->CreateInstance(pUnkOuter, riid,ppv);
            pIFactory->Release();
      }
}

     可以看到CoCreateInstance首先调用CoGetClassObject来获取类厂中的ICalssFactory接口指针,再通过ICalssFactory::CreateInstance完成新组件的创建。

    

3.类厂的实现


     DllGetClassObject的使用


     CoGetClassObject需要DLL中的一个特定函数来创建组件的类厂。此函数就是DllGetClassObject。
HRESULT  __stdcall  DllGetClassObject(
      __in REFCLSID rclsid,
      __in REFIID riid,
      __deref_out LPVOID FAR* ppv
);
这三个参数和CoGetClassObject的三个参数是相同的,将CLSID传给DllGetClassObject可以是DLL支持任意数目的组件,DllGetClassObject可以用CLSID来选择合适的类厂。
 

    组件的创建过程


     首先客户通过CoGetClassObject来启动组件的创建过程。其次是Com库他实现了CoGetClassObject函数,第三是DLL,其中实现了被CoGetClassObject叼哦那个的DllGetClassObject函数,DllGetClassObject函数的任务就是创建客户所请求的类厂。创建玩类厂后客户将使用ICalssFactory接口来创建相应的组件。

4.同一DLL中的多个组件


     将待创建的组件CLSID传给DllGetClassObject来创建相应的类厂。
     

5.DLL的卸载


     COM库实现了一个名为CoFreeUnusedLibraries函数以释放哪些不在使用的库,但何时不再使用库呢?CoFreeUnusedLibraries将调用DllCanUnloadNew以询问DLL是否可以被卸载。LockServer给客户提供了一种将服务器保存在内存中,直到使用完毕的方法,客户需要调用LockServer(True)锁住服务器。使用完毕后就可以使用LockServer(False)解锁。


原文地址:https://www.cnblogs.com/javawebsoa/p/3078617.html