zoukankan      html  css  js  c++  java
  • COM组件对象模型基础

    COM组件对象模型

    COM组件对象模型是为了创建一种独立于任何编程语言的对象。COM对象提供统一的接口,在不同的编程环境中通过调用COM对象特定接口的方法来完成特定的任务。一般有三种方式编写COM组件:COM SDK,MFC,ATL

    COM组件分类

    • 一个DLL(进程内组件)。
      方法与客户进程在同一地址空间下,可直接访问到。
    • 一个本地运行的EXE(进程外组件,本地服务器)。
      方法与客户进程在同一机器的不同地址空间中,通过LPC(本地过程调用)访问。
    • 一个远程机器上运行的EXE(进程外组件,远程服务器)。
      方法与客户进程在不同机器上,通过RPC(远程过程调用)。

    COM对象和接口

    一个COM组件可以含有多个COM对象,一个COM对象可以含有多个接口,一个接口可以含有多个方法。
    为了在COM组件中唯一标识一个COM对象类,每一个COM对象类都有一个特定的标识符(CLSID),这个标识符是一个128位的数值。同样对于不同的接口而言也有一个标识符(IID),也是一个128位的数值。

    IUnknown接口

    //IUnknown接口的方法
    QueryInterface                  //返回指向另一个接口的指针
    AddRef                          //增加对象的引用计数
    Release                         //减少对象的引用计数
    

    每一个COM对象应该了IUnknown接口,而且为了通过对象任意一个接口指针都能调用其他接口,需要所有的接口处理实现自己的特定的方法外,还都要实现以上三种方法(每一个接口都继承IUnknown接口)。

    HRESULT QueryInterface()
    {
          return (指定接口类*)this;
    }
    

    如果使用MFC实现COM,因为其采用多继承,而接口类的方法都是写成虚函数,COM对象类继承众多接口类会含有多个虚表(vtable),所以QueryInterFace返回的对应接口类的指针时需要强制类型转换(将this指针偏移到指定接口类的vtable处),这样就不会出错误调用到其他接口的方法。ATL实现COM采用的是嵌套类,其直接返回对应的接口指针。

    ULONG AddRef()
    {
          return ++m_lRef;
    }
    
    ULONG Release()
    {
          if(--m_lRef == 0)
          {
                delete this;
                return 0;
          }
    }
    

    因为COM对象是有生命周期的,而且运行在EXE上的COM对象可供多个客户使用,每多一个用户就会调用AddRef增加一次引用计数。如果某个客户使用了COM对象,应该在最后不使用COM对象的时候调用Release方法减少对象的引用计数。当对象的引用计数减为零时对象就会销毁。

    名称解析代理/桩基模块DLL

    客户拥有的接口指针实际上是指向名称解析代理,它实现了与真实的对象相同的接口和方法。当客户调用对象中的方法时,调用传到名称解析代理,名称解析代理将使用某种LPC将调用提交给桩基模块。桩基模块展开方法参数并调用对象,然后将返回值调度会名称解析代理。如果是标准接口就不需要提供名称解析代理和桩基模块,但是如果是自定义接口就需要提供,而VC++带有一个MIDI的编译器,用来编译IDL(接口定义语言)文件,为名称解析代理和桩基模块提供源程序。

    实例化COM对象

    接口名称 * pName1;
    HRESULT hr = CoCreateInstance(对象CLSID, NULL, CLSCTX_SERVER, 接口IID, (void**)&pName1);
    
    另一个接口名称 * pName2;
    hr = pName2->QueryInterface(接口IID, (void**)&pName2);
    
    pName2->Release();
    pName1->Release();
    

    通过传递给CoCreateInstance函数CLSID实例化COM类,实际其是先实例化CLSID对象对应的"类工厂","类工厂"也是一个COM对象,然后通过"类工厂"的IClassFactory接口的CreateInstance方法来创建CLSID对应的COM类对象。(每一个COM对象都有与其对应的“类工厂”)

  • 相关阅读:
    小程序开发-7-访问api数据与ES6在小程序中的应用
    小程序开发-8-流行页面编码与组件的细节知识
    小程序开发-6-组件数据、事件与属性
    当安装mongodb客户端出现了Failed to load list of databases
    对bluebird的理解
    百度地图实现案例
    iScroll实现下拉刷新上拉加载
    nodejs环境变量配置
    检测Python程序本身是否已经在运行
    用Python快速找到出现次数最多的数据
  • 原文地址:https://www.cnblogs.com/revercc/p/14059025.html
Copyright © 2011-2022 走看看