zoukankan      html  css  js  c++  java
  • 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)解锁。


  • 相关阅读:
    大爽Python入门教程 3-1 布尔值: True, False
    以太坊中的账户、交易、Gas和区块Gas Limit
    全链路压力测试经验
    全链路压力测试
    腾讯大牛教你ClickHouse实时同步MySQL数据
    数据湖和数据仓库的区别?
    第六次作业
    linux CPU实时频率命令
    没有Flash如何做直播
    如何扩展srs并发能力
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3078617.html
Copyright © 2011-2022 走看看