浅谈COM组件

1、COM组件和COM接口
COM组件可以用C++的抽象基类来定义COM接口,对于COM组件来说,必须继承的最基本的COM接口:IUnknow,这个接口内部有三个函数:

  • QueryInterface
  • AddDef
  • Release
interface IUnknow
{
	virtual HRESULT QueryInterface(const IID &iid,void **ppv)= 0;
	virtual ULONG AddDef() = 0;
	virtual ULONG Release() = 0;
}

2、QueryInterface
用处:查询某个组件是否支持某个特定的接口,如果支持,该函数返回一个指向该接口的指针
返回类型:HRESULT的含义如下:
在这里插入图片描述
参数类型:IID
IID是一个接口标识符。
每个接口可以设置一个IID,用于标志该接口,标志了某个接口之后,IID的值不能再修改。
实际上,GUID和IID的关系如下

typedef GUID IID;//IID是GUID的一个别名

至于GUID,它是一个唯一标识DLL和EXE文件的标识符,用设备MAC地址、时间戳、随机数三重信息,确保生成一个相对唯一的标识符。

3、AddDef 和Release
用于引用计数技术,判断某个组件何时应该被释放资源(引用数为0时)
AddDef:组件引用计数增加1,可以在组件函数返回之前或者赋值之后进行调用。
Release:组件引用计数减少1,当引用计数为0时,释放组件自身的内存资源,可以在接口使用完之后调用。

4、IDispatch接口
对于Javascript等解释性语言,需要通过自动化技术来调用COM组件的自定义接口。这类组件是支持IDispatch技术的。
IDispatch接口接受一个函数的字符串名称,执行这个函数
对于Javascript这类解释性语言来说,要调用COM组件中的自定义接口,需要把自定义接口中的函数名称和参数传给IDispatch,让IDispatch接口间接执行。
IDispatch接口中有两个函数:GetDsOfNames和Invoke。
GetDsOfNames函数读取一个函数名称,返回它的调度ID
Invoke函数接受调度ID和函数参数,执行调度ID对应的函数功能。

总结:只要我们的COM组件支持IDispatch接口,那么就能在Javescript之类的解释性语言中使用我们设置的COM组件。且IDispatch接口一般不需要手动设置。

5、COM组件的数据类型
在这里插入图片描述

挑点比较特殊的说明一下
(1)VARIANT_BOOL及其指针在这里插入图片描述
(2)BSTR及其指针
在这里插入图片描述
和BSTR相关的COM中的函数

  • COM组件中申请构造BSTR字符串:
BSTR SysAllocString(const OLECHAR*)
  • 根据字符串指针和字符个数构造BSTR字符串:
BSTR SysAllocStringLen(const OLECHAR *,UINT)
  • 获取字符串前的计数值
UINT SysStringLen(BSTR)
  • 释放字符串
void SysFreeString(BSTR)

(3)IUnknow及其指针
在这里插入图片描述
(4)IDispatch
及其指针
在这里插入图片描述
(5)VARIANT及其指针
这是一个体现COM组件跨语言性的数据类型,可以存储任意类型的数据,通俗的说,它是一个“万能数据类型”。
在C++中,VARIANT是一个结构体,内部有联合体,

//可以在VS安装目录下\VC\PlatformSDK\Include\oaidl.h文间中查看结构体定义
struct  tagVARIANT
    {
    union 
        {
        struct  __tagVARIANT
            {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union 
                {
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                _VARIANT_BOOL bool;
                SCODE scode;
                CY cyVal;
                DATE date;
                BSTR bstrVal;
                IUnknown __RPC_FAR *punkVal;
                IDispatch __RPC_FAR *pdispVal;
                SAFEARRAY __RPC_FAR *parray;
                BYTE __RPC_FAR *pbVal;
                SHORT __RPC_FAR *piVal;
                LONG __RPC_FAR *plVal;
                FLOAT __RPC_FAR *pfltVal;
                DOUBLE __RPC_FAR *pdblVal;
                VARIANT_BOOL __RPC_FAR *pboolVal;
                _VARIANT_BOOL __RPC_FAR *pbool;
                SCODE __RPC_FAR *pscode;
                CY __RPC_FAR *pcyVal;
                DATE __RPC_FAR *pdate;
                BSTR __RPC_FAR *pbstrVal;
                IUnknown __RPC_FAR *__RPC_FAR *ppunkVal;
                IDispatch __RPC_FAR *__RPC_FAR *ppdispVal;
                SAFEARRAY __RPC_FAR *__RPC_FAR *pparray;
                VARIANT __RPC_FAR *pvarVal;
                PVOID byref;
                CHAR cVal;
                USHORT uiVal;
                ULONG ulVal;
                INT intVal;
                UINT uintVal;
                DECIMAL __RPC_FAR *pdecVal;
                CHAR __RPC_FAR *pcVal;
                USHORT __RPC_FAR *puiVal;
                ULONG __RPC_FAR *pulVal;
                INT __RPC_FAR *pintVal;
                UINT __RPC_FAR *puintVal;
                struct  __tagBRECORD
                    {
                    PVOID pvRecord;
                    IRecordInfo __RPC_FAR *pRecInfo;
                    } __VARIANT_NAME_4;
                } __VARIANT_NAME_3;
            } __VARIANT_NAME_2;
        DECIMAL decVal;
        } __VARIANT_NAME_1;
    };

和VARIANT相关的函数

  • 初始化一个VARIANT变量
VariantInit()
//将vt域设置为VT_EMPTY,表示空类型
//vt域主要用来指示VARIANT结构体中的联合体应该保存何种数据类型。
  • 清除一个VARIANT变量
VariantClear()

VARIANT的赋值需要赋值vt域名和实际的数值
详细可见下方“6、COM组件中的数据类型转换”例子中的var赋值操作。

6、COM组件中的数据类型转换
两个例子
在这里插入图片描述
在这里插入图片描述
7、VARIANT类型的派生类
由于对VARIANT赋值不方便,因此,使用VARIANT的派生类,拓展该类型的使用方式,可以简化操作
目前已有的VARIANT派生类有_variant_t、CComVariant、COLeVariant等

(1)_variant_t的定义:
在Visual Studio安装目录\VC\include\comutil.h中定义。
详见此链接
(2)CComVariant的定义:
在Visual Studio 安装目录\VC\atlmfc\include\atlcomcli.h中定义。

构造时会自动调用VARIANTInit()函数
析构时会自动调用VARIANTClear()函数

构造、赋值、清除等操作可见此博客

(3)COLeVariant
在Visual Studio 安装目录\VC\atlmfc\include\afxdisp.h中定义

以上就是COM组件入门的一些基础知识啦,参考的是《COM实用入门教程》这份资料。

之后如果我操作顺利的话,还会更新COM组件的创建和注册等操作哒。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值