• com组件接口


    int main( int argc, char *argv[] )
    {
       cout << "Initializing COM" << endl;
     
       if ( FAILED( CoInitialize( NULL )))
       {
          cout << "Unable to initialize COM" << endl;
          return -1;
       }
     
       ISampleMath* pSampleMath;
       HRESULT hr;
       // This time use CoCreateInstance
       hr = CoCreateInstance( CLSID_SampleMath,
                              NULL,
                              CLSCTX_LOCAL_SERVER,
                              IID_ISampleMath,
                              (void**) &pSampleMath );
     
       if ( FAILED( hr ))
       {
          cout << "Failed to create server instance. HR = " << hr << endl;
          CoUninitialize();
          return -1;
       }
     
       // Access the IMath interface
       long lResult;
       pSampleMath->Add( 134, 353, &lResult );
       cout << "134 + 353 = " << lResult << endl;
     
     
     
       // Release all of our interfaces
       if ( pSampleMath )
     
       CoUninitialize();
     
       return 0;
    }
     
     

    COM组件可以是一个Dll(进程内组件),也可以是一个EXE(进程外组件)。进程内组件就是组件和客户程序在同一进程内,进程外组件即组件和客户程序分别有自己的进程空间。

        一个COM组件可以包含多个COM对象,一个COM对象又可以有多个接口。

    第2章 COM对象和接口

    2.1 CLSID和IID

        对于COM对象来说,接口是它与外界进行交互的唯一途径。

        每个COM对象,可以用CLSID来标识,COM对象的每个接口可以用IID来标识。CLSID和IID都是128位的标识符GUID,是一个随机数,可以由两方面特性来保证:空间(如网络适配器地址)和时间。

        GUID可以通过COM库的API函数生成:

    HRESULT CoCreateGuid( GUID * pguid );
    2.1.2 COM对象和C++对象的不同
    COM对象的数据成员封装以组建模块为最终边界,对于对象用户是完全透明的、不可见的,用户必须通过接口方法来访问数据成员;C++对象的封装特性只是语义上的,用户可以直接看到数据成员。
    2.2 COM接口结构
    COM组件开发知识重点——COM原理与应用篇(一)
    接口是包含了一组函数的数据结构。客户程序利用这些函数获得组件对象的服务。接口成员函数中的字符串变量必须使用Unicode字符指针。
    客户程序用一个指向接口数据结构的指针来调用接口成员函数,接口指针又指向pVtable(指向vtable的指针),pVtable指向一组函数,称为接口函数表(虚函数表vtable),表中每一项为4个字节长的函数指针,每个函数指针再指向函数的具体实现。
    2.2.2 接口描述语言IDL
    2.3 IUnknown接口
    COM定义的每个接口都必须从IUnknown接口继承过来,因为IUnknown接口提供了两个重要特性:生存期控制和接口查询。
    COM组件开发知识重点——COM原理与应用篇(一)
    QueryInterface用于查询COM对象的其他接口指针,AddRef和Release用于对引用计数进行操作。
    在COM对象级实现引用计数,精细度比较合适。

    2.3.1 使用引用计数规则

    (1)函数的参数中使用接口指针变量。

    输入参数:在被调用函数中,不必调用AddRef和Release函数。

    输出函数:在被调用函数返回之前,对输出参数调用AddRef,增加引用计数。

    输入-输出参数:在参数被修改之前,对原来传进来的接口指针调用Release,引用计数减1,在参数被修改之后,对新的接口指针变量指针调用AddRef,若在函数执行过程中,参数没有被修改,则不必调用AddRef和Release函数。

    (2)局部接口指针变量。

    在局部函数块中,一个局部接口指针变量被赋了值并调用了接口成员函数,则对该局部接口指针变量不必调用AddRef和Release函数。
    (3)全局接口指针变量。
    在把全局接口指针变量作为输入参数传给某个函数之前,调用AddRef,在函数返回之后调用Release。
    (4)C++中类成员变量为接口指针变量:适用于(3)。
    (5)在顺序执行过程中,如果对一个接口指针变量赋值,则对赋值后的接口指针变量调用AddRef,如果赋值前的接口指针变量还没有结束,则赋值前必须对它调用Release以便先结束它的使用。

    COM的实现

    3.1 进程内组件(DLL)的实现,可以参考DLL技术,主要参数为:

    1)LoadLibrary:装载DLL模块

    2)GetProcAddress:取引出函数的地址

    3)FreeLibrary:释放DLL模块

        COM采用LPC(本地过程调用)和RPC(远程过程调用)的方法进行进程之间的通信,LPC用于在同一机器上的不同进程之间进行通信,而RPC用于在不同机器上的进程之间进行通信。

    COM组件开发知识重点——COM原理与应用篇(二)3.2 组件程序的两个用于注册的入口函数为DllRegisterServer和DllUnregisterServer,注册组件使用命令:RegSvr32 *.dll;反注册组件使用命令:RegSvr32 /u *.dll,进程内组件注册使用此命令。进程外组件注册必须支持两个命令行参数/RegServer 和/UnregServer。
    3.3 类厂

        COM库通过类厂创建COM对象,对应每一个COM类,都有一个类厂专门用于该COM类的对象创建工作。类厂本身也是一个COM对象,它支持接口IClassFactory。

    COM组件开发知识重点——COM原理与应用篇(二)CreateInstance创建对应的COM对象,LockServer控制组件的生存周期。

    类厂由函数DllGetClassObject创建。

    COM组件开发知识重点——COM原理与应用篇(二)DllGetClassObject返回类厂对象的接口指针,再通过CreateInstance创建对应的COM对象。
    3.3.2 COM库与类厂的交互

        创建对象函数:

    1)若创建远程对象或希望一次获取对象的多个接口指针,选用CoCreateInstanceEx。

    COM组件开发知识重点——COM原理与应用篇(二)

    2)若希望获取类厂对象或要调用类厂的某些成员函数,选用CoGetClassObject,通常IID=IID_IclassFactory,进程内组件直接调用DLL的CoGetClassObject,若CoGetClassObject创建的类厂对象位于进程外组件,函数启动组件进程,然后等待,直到组件进程把它支持的COM类对象的类厂注册到COM中,返回类厂信息。

    COM组件开发知识重点——COM原理与应用篇(二)

    3)其他情况下,选用CoCreateInstance创建对象,CoCreateInstance封装类厂创建对象的过程,返回COM对象的接口指针,不能创建远程机器上的对象。

    COM组件开发知识重点——COM原理与应用篇(二)COM组件开发知识重点——COM原理与应用篇(二)
    3.4 COM库

        COM库初始化函数:CoInitialize

        COM库终止函数:CoUninitialize

    3.4.2 COM库的内存管理

        COM提供的内存管理器标准,是一个COM接口IMalloc。当组件内存的分配和释放不在同一模块,需要用到内存管理器,COM库封装了三个API函数,用于内存分配和释放

    CoTaskMemAlloc

    CoTaskMemFree
    CoTaskMemRealloc

    3.4.3 组件程序的装载和卸载

    1)进程内组件的装载、卸载

    2)进程外组件的装载、卸载

        组件程序满足两个条件才可以被卸载:组件中对象数为0;类厂的锁计数器为0。此时,DllCanUnloadNow返回TRUE。

        在判断返回类型HRESULT时,需用宏SUCCEEDED和FAILED。

  • 相关阅读:
    进程管理
    linux进程间的通信方式
    linux进程调度的算法
    安装haroopad
    SAE部署Java应用
    Jetty 8.1 安装 运行 部署
    javaweb学习总结(五)——Servlet开发(一)
    eclipse打war包
    Java基础学习总结——Java对象的序列化和反序列化
    Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5925790.html
Copyright © 2020-2023  润新知