zoukankan      html  css  js  c++  java
  • COM组件(ATL篇)

    1创建进程内组件    1

    1.1 目标    1

    1.2 创建项目    3

    1.2.1 VC++6.0    3

    1.2.2 VC++2010    5

    1.3 增加COM    6

    1.3.1 VC++6.0    6

    1.3.2 VC++2010    8

    1.3.3 项目结构    12

    1.4 增加方法    13

    1.4.1 VC++6.0    13

    1.4.2 VC++2010    14

    1.5 增加属性    16

    1.5.1 VC++6.0    16

    1.5.2 VC++2010    17

    1.6 删除方法、属性    17

    1.7 编码    17

    1.7.1 增加成员变量    17

    1.7.2 初始化成员变量    18

    1.7.3 实现Add    18

    1.7.4 实现Reset    18

    1.7.5 实现get_Count    18

    1.7.6 实现get_Average    19

    1.7.7 实现get_StdDev    19

    1.8 注册、注销    19

    2 VC++使用组件    21

    2.1 #import    21

    2.2 MFC包装类    21

    2.3 C语言调用    21

    1创建进程内组件

    1.1 目标

    本章的目标是使用ATL创建一个进程内COM组件。在此组件里,将实现COMCStatisticCOM接口IStatistic,用来进行统计计算。IStatistic的详细信息如下:

    1、方法

    void Reset();                //重新开始统计计算

    void Add(double dVal);        //增加一个数据

    2、属性

    long    Count;                //返回数据个数

    double    Average;            //返回平均值

    double    StdDev;            //返回标准差

    CStatisticVC++代码如下:

    #include <MATH.H>

     

    class CStatistic

    {

    public:

    CStatistic()            {Reset();}

    public:

    void Reset()        {memset(this,0,sizeof(*this));}

    void Add(double dVal)

    {

    ++m_nCount;                         //样本个数

    m_dSum += dVal;             //所有样本值的和

    m_dSum2 += dVal * dVal;     //所有样本值的平方和

    }

    public://属性定义(VC++的语法)

    __declspec(property(get=GetCount)) ULONG    Count;

    __declspec(property(get=GetAverage))     double        Average;

    __declspec(property(get=GetStdDev))     double        StdDev;

    public:

    ULONG GetCount() const        {return m_nCount;}

    double GetAverage() const

    {

    if(m_nCount)

    {

    return m_dSum / m_nCount;

    }

    return 0.0;

    }

    double GetStdDev() const

    {

    double d = 0.0;

    if(m_nCount > 1)

    {

    d = (m_nCount * m_dSum2 - m_dSum * m_dSum)

    / (m_nCount * (m_nCount - 1));

    if(d > 0.0)

    {

    d = sqrt(d);

    }

    }

    return d;

    }

    private:

    ULONG    m_nCount;     //样本个数

    double        m_dSum;     //所有样本值的和

    double        m_dSum2;     //所有样本值的平方和

    };

    测试代码如下:

    ULONG    n    =    0;

    double        d    =    0.0;

    CStatistic    s;

    s.Reset();

    s.Add(1.0);

    s.Add(2.0);

    s.Add(3.0);

    s.Add(4.0);

    n = s.Count; //(1,2,3,4)的个数

    d = s.Average; //(1,2,3,4)的平均值

    d = s.StdDev; //(1,2,3,4)的标准差

    s.Add(5.0);

    n = s.Count; //(1,2,3,4,5)的个数

    d = s.Average; //(1,2,3,4,5)的平均值

    d = s.StdDev; //(1,2,3,4,5)的标准差

    这个类的优点在于:它能实时获得样本数据的平均值、标准差,且不用把样本数据存入数组,因此可以连续的长时间工作。

    1.2 创建项目

    1.2.1 VC++6.0

    运行VC++6.0,新建"ATL COM AppWizard"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。

    图1.1

    显示界面如下所示,直接单击"Finish"按钮。

    图1.2

    显示界面如下,单击"OK"按钮,完成项目创建。

    图1.3

    1.2.2 VC++2010

    运行VC++2010,新建"ATL Project"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。

    图1.4

    显示创建向导,界面如下面两张图所示:

    图1.5 创建向导——页面一

    图1.6 创建向导——页面二

    单击上图的"Finish"按钮,完成项目的创建。

    1.3 增加COM

    现在,往项目里增加COM类。

    1.3.1 VC++6.0

    单击【Insert】【New ATL Object...】菜单项

    图1.7

    显示界面如下。请选中"Objects"里的"Simple Object",然后单击"Next"按钮。

    图1.8

    显示界面如下,一共有两个页面。

    图1.9 增加COM类——页面一

    下图所示界面里,Interface有两个选项:Dual表示双接口(也叫自动化接口),它派生自IDispatchCustom表示自定义接口,它派生自IUnknown。自定义接口直接访问虚函数表,其效率较高。自动化接口效率较低,但是它支持的语言较多。

    图1.10 增加COM类——页面二

    1.3.2 VC++2010

    单击【Project】【Add Class...】菜单项

    图1.11

    选中"ATL Simple Object",然后单击"Add"按钮

    图1.12

    显示界面如下,一共有三个页面

    图1.13 增加COM类——页面一

    图1.14 增加COM类——页面二

    图1.15 增加COM类——页面三

    1.3.3 项目结构

    VC++6.0的类视图里增加了"CStatistic"和"IStatistic"。

    IStatisticCOM接口,客户端程序通过它访问COM组件。

    CStatisticCOM类,真正的工作由它来完成。

    图1.16

    同时,idl文件也发生了变化,如下表所示。增加了接口IStatistic,增加了COMStatistic,这个COM类实现了接口IStatistic

    // comDLLatl.idl

    import "oaidl.idl";

    import "ocidl.idl";

    [

        uuid(0FEBC618-38BC-4A5B-AE09-3C56635F4D73),

        version(1.0),

        helpstring("comDLLatl 1.0 Type Library")

    ]

    library COMDLLATLLib

    {

        importlib("stdole32.tlb");

        importlib("stdole2.tlb");

        [

            object,

            uuid(7FB59FA6-E715-4C23-9520-DE93293E0B5F),    

            helpstring("IStatistic Interface"),

            pointer_default(unique)

        ]

        interface IStatistic : IUnknown

        {

        };

        [

            uuid(471BF24D-B793-44A1-9205-7BF36A6EB698),

            helpstring("Statistic Class")

        ]

        coclass Statistic

        {

            [default] interface IStatistic;

        };

    };

    1.4 增加方法

    1.4.1 VC++6.0

    鼠标右键单击接口IStatistic,弹出菜单中单击【Add Method...】菜单项

    图1.17

    下图就是增加方法的界面。这里增加了方法void Add(double dVal)。单击"OK"按钮,完成方法的增加。注意:对于自动化接口,Return Type只能是HRESULT

    图1.18

    可使用同样的方法,增加方法void Reset()

    1.4.2 VC++2010

    鼠标右键单击接口IStatistic,弹出菜单中单击【Add】【Add Method...】。

    图1.19

    增加方法的界面如下。与VC++6.0的大致相同。单击"Finish"按钮,完成方法void Add(DOUBLE dVal)的添加。

    图1.20

    可使用同样的方法,增加方法void Reset()

    1.5 增加属性

    1.5.1 VC++6.0

    在图1.17中,单击【Add Property...】菜单项。显示界面如下:

    这里增加了属性long Count。注意:没有设置"Put function",说明这个属性是只读属性。

    单击"OK"按钮,完成属性的增加。

    图1.21

    同样方法,可以增加属性double Averagedouble StdDev

    1.5.2 VC++2010

    在图1.19中,单击【Add Property...】菜单项。显示界面如下:

    这里增加了属性ULONG Count。注意:没有设置"Put function",说明这个属性是只读属性。

    单击"Finish"按钮,完成属性的增加。

    图1.22

    同样方法,可以增加属性double Averagedouble StdDev

    1.6 删除方法、属性

    使用ATL,删除属性、方法,似乎只能手动进行,相当的麻烦。

    1.7 编码

    1.7.1 增加成员变量

    请给CStatistic增加三个成员变量

    private:

    ULONG    m_nCount;

    double        m_dSum;

    double        m_dSum2;

    1.7.2 初始化成员变量

    CStatistic的构造函数里,初始化这三个成员变量

    CStatistic()

    {

    m_nCount        =    0;

    m_dSum        =    0.0;

    m_dSum2        =    0.0;

    }

    1.7.3 实现Add

    STDMETHODIMP CStatistic::Add(double dVal)

    {

    ++m_nCount;             //样本个数

    m_dSum += dVal;         //所有样本值的和

    m_dSum2 += dVal * dVal;     //所有样本值的平方和

    return S_OK;

    }

    1.7.4 实现Reset

    STDMETHODIMP CStatistic::Reset()

    {

    m_nCount = 0;

    m_dSum = 0.0;

    m_dSum2 = 0.0;

    return S_OK;

    }

    1.7.5 实现get_Count

    STDMETHODIMP CStatistic::get_Count(long *pVal)

    {

    *pVal = m_nCount;

    return S_OK;

    }

    1.7.6 实现get_Average

    STDMETHODIMP CStatistic::get_Average(double *pVal)

    {

    if(m_nCount)

    {

    *pVal = m_dSum / m_nCount;

    }

    else

    {

    *pVal = 0.0;

    }

    return S_OK;

    }

    1.7.7 实现get_StdDev

    STDMETHODIMP CStatistic::get_StdDev(double *pVal)

    {

    *pVal = 0.0;

    if(m_nCount > 1)

    {

    *pVal = (m_nCount * m_dSum2 - m_dSum * m_dSum)

    / (m_nCount * (m_nCount - 1));

    if(*pVal > 0.0)

    {

    *pVal = sqrt(*pVal);

    }

    }

    return S_OK;

    }

    1.8 注册、注销

    编译comDLLatl,即可得到进程内COM组件comDLLatl.dll。使用它之前,需要注册。

    注册组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllRegisterServer函数

    regsvr32 comDLLatl.dll

    Rundll32 comDLLatl.dll,DllRegisterServer

    注销组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllUnregisterServer函数

    regsvr32 /u comDLLatl.dll

    Rundll32 comDLLatl.dll,DllUnregisterServer

    注意:VC++2010可以编译生成64位的COM组件。在64位操作系统上,regsvr32.exeRundll32.exe将自动识别COM组件是32位的还是64位的。注册信息会写入注册表的如下几个位置。注意这里的<ProgID>其实就是comDLLatl.Statistic

    HKEY_LOCAL_MACHINESOFTWAREClassesTypeLib

    HKEY_LOCAL_MACHINESOFTWAREClassesInterface

    HKEY_LOCAL_MACHINESOFTWAREClassesCLSID

    HKEY_LOCAL_MACHINESOFTWAREClasses<ProgID>

    对于64位组件,注册程序直接访问上述注册表项;对于32位组件,注册程序会将上述注册表项映射至32位的注册表项。如此一来,同一个组件的32位、64位是可以同时注册在64Windows上的,它们互不干涉。

    2 VC++使用组件

    2.1 #import

    请参考《COM组件(MFC)》。需要注意的是:MFC创建的COM组件,其接口必定是Dual接口(图1.10、图1.15中的Interface选项),也就是派生自IDispatch的自动化接口。ATL可以创建Custom接口,这种接口将派生自IUnknowntli文件里的函数通过虚函数实现,效率较高。Custom接口的不足之处在于:它可能不能被某些脚本语言(如:VBS)调用。

    2.2 MFC包装类

    如果接口是Dual接口,就可以生成MFC包装类。具体操作请参考《COM组件(MFC)》。

    2.3 C语言调用

    使用C语言也可以访问COM组件。

    如果接口是Dual接口,请参考《COM组件(MFC)》。

    如果接口是Custom接口,则可以使用编译类型库时产生的C/C++头文件。如下面这段代码:(节选自comDLLatl_i.h

    #define IStatistic_Add(This,dVal)          ((This)->lpVtbl->Add(This,dVal))

    #define IStatistic_get_Count(This,pVal)    ((This)->lpVtbl->get_Count(This,pVal))

    亦即:可以通过宏IStatistic_AddIStatistic_get_Count去访问方法、属性。

  • 相关阅读:
    HDU1272---(并查集)简单应用
    HDU1232 畅通工程---(经典并查集应用)
    HDU 1877 又一版 A+B(进制转换)
    L1-020. 帅到没朋友
    L2-001. 紧急救援---(Dijkstra,记录路径)
    JVM Class字节码之三-使用BCEL改变类属性
    JVM Class详解之一
    Jvm原理剖析与调优之内存结构
    虚拟化的发展历程和实现原理——图文详解
    JVM学习笔记(四)------内存调优
  • 原文地址:https://www.cnblogs.com/hanford/p/6103069.html
Copyright © 2011-2022 走看看