VARIANT和CComVariant

VARIANT

1.定义

VARIANT,变体数据类型,在文件OAIDL.IDL中定义

VARIANT数据结构包含两个域(如果不考虑保留的域)。

vt域描述了第二个域的数据类型。

为了使多种类型能够在第二个域中出现,我们定义了一个联合结构。

所以,第二个域的名称随着vt域中输入值的不同而改变。

简单来说VARIANT主要由一个变量类型vt(枚举值)和一个联合体(变量内容)组成。

struct tagVARIANT {
     union {
         struct __tagVARIANT {
             VARTYPE vt;
             WORD     wReserved1;
             WORD     wReserved2;
             WORD     wReserved3;
             union {
                 ULONGLONG      ullVal;        /* VT_UI8                */
                 LONGLONG       llVal;         /* VT_I8                 */
                 LONG           lVal;          /* VT_I4                 */
                 BYTE           bVal;          /* VT_UI1                */
                 SHORT          iVal;          /* VT_I2                 */
                 FLOAT          fltVal;        /* VT_R4                 */
                 DOUBLE         dblVal;        /* VT_R8                 */
                 VARIANT_BOOL   boolVal;       /* VT_BOOL               */
                 _VARIANT_BOOL bool;          /* (obsolete)            */
                 SCODE          scode;         /* VT_ERROR              */
                 CY             cyVal;         /* VT_CY                 */
                 DATE           date;          /* VT_DATE               */
                 BSTR           bstrVal;       /* VT_BSTR               */
                 IUnknown *     punkVal;       /* VT_UNKNOWN            */
                 IDispatch *    pdispVal;      /* VT_DISPATCH           */
                 SAFEARRAY *    parray;        /* VT_ARRAY              */
                 BYTE *         pbVal;         /* VT_BYREF|VT_UI1       */
                 SHORT *        piVal;         /* VT_BYREF|VT_I2        */
                 LONG *         plVal;         /* VT_BYREF|VT_I4        */
                 LONGLONG *     pllVal;        /* VT_BYREF|VT_I8        */
                 FLOAT *        pfltVal;       /* VT_BYREF|VT_R4        */
                 DOUBLE *       pdblVal;       /* VT_BYREF|VT_R8        */
                 VARIANT_BOOL *pboolVal;      /* VT_BYREF|VT_BOOL      */
                 _VARIANT_BOOL *pbool;        /* (obsolete)            */
                 SCODE *        pscode;        /* VT_BYREF|VT_ERROR     */
                 CY *           pcyVal;        /* VT_BYREF|VT_CY        */
                 DATE *         pdate;         /* VT_BYREF|VT_DATE      */
                 BSTR *         pbstrVal;      /* VT_BYREF|VT_BSTR      */
                 IUnknown **    ppunkVal;      /* VT_BYREF|VT_UNKNOWN   */
                 IDispatch **   ppdispVal;     /* VT_BYREF|VT_DISPATCH */
                 SAFEARRAY **   pparray;       /* VT_BYREF|VT_ARRAY     */
                 VARIANT *      pvarVal;       /* VT_BYREF|VT_VARIANT   */
                 PVOID          byref;         /* Generic ByRef         */
                 CHAR           cVal;          /* VT_I1                 */
                 USHORT         uiVal;         /* VT_UI2                */
                 ULONG          ulVal;         /* VT_UI4                */
                 INT            intVal;        /* VT_INT                */
                 UINT           uintVal;       /* VT_UINT               */
                 DECIMAL *      pdecVal;       /* VT_BYREF|VT_DECIMAL   */
                 CHAR *         pcVal;         /* VT_BYREF|VT_I1        */
                 USHORT *       puiVal;        /* VT_BYREF|VT_UI2       */
                 ULONG *        pulVal;        /* VT_BYREF|VT_UI4       */
                 ULONGLONG *    pullVal;       /* VT_BYREF|VT_UI8       */
                 INT *          pintVal;       /* VT_BYREF|VT_INT       */
                 UINT *         puintVal;      /* VT_BYREF|VT_UINT      */
                 struct __tagBRECORD {
                     PVOID          pvRecord;
                     IRecordInfo * pRecInfo;
                 } __VARIANT_NAME_4;          /* VT_RECORD             */
             } __VARIANT_NAME_3;
         } __VARIANT_NAME_2;
         DECIMAL decVal;
     } __VARIANT_NAME_1;
};

2.实例

long lValue = 999;
VARIANT vParam;
vParam.vt = VT_I4;//指定数据类型,常量VT_I4表明在第二个域中将出现一个long型的数据
vParam.lVal = lValue;//一个long型数据存入VARIANT类型时,其第二个域使用的名称是lVal

3.作用

VARIANT类型,可以跨语言(VB, C#, Java, C++)来表示任意一种类型。和BSTR一样,它也是微软约定好的一种协议。遵循这种协议,我们的变量可以正确地被支持COM的语言所认识。

4.API

VariantInit(VARIANTARG* pvarg)

初始化一个VARIANT(VARIANTARG是VARIANT别名)变量,它将变量初始化为VT_EMPTY

VariantClear(VARIANTARG * pvarg)

清理一个VARIANT对象。当调用完VariantClear后,变量的vt将会被设置为VT_EMPTY。

VariantCopy(VARIANTARG *pvargDest, const VARIANTARG *pvargSrc)

将pvargSrc中的内容拷贝到pvargDest中。如果pvargDest事先有内容,那么则使用VariantClear来释放它。

VARIANT a, b;
VariantInit(&a);
VariantInit(&b);
VariantCopy(&a, &b); // 释放a中的内容,然后a<-b
VariantClear(&a);
VariantClear(&b);

CComVariant

1.定义

类(class),在ATL中定义,是直接继承于VARIANT类的,所以它可以直接使用VARIANT成员。

头文件 :atlcomcli.h

析构函数:调用Clear()方法,也就是调用VariantClear()。

构造函数:

第一类是没有参数的构造函数,简单地调用了VariantInit。

第二类是传入值变量的构造函数,例如传入BYTE, short等,vt将分别设置为VT_UI1, VT_I2,且设置到对应的成员中。

第三类转调了自身的operator=

可以将CComVariant看为“智能VARIANT”,我们只需要给它传入适当的值,它自己来处理VARIANT的生命周期,并且它符合我们绝大部分需求

2.实现

(1) 构造

默认构造函数:CComVariant()

BYTE构造函数:CComVariant(BYTE  nSrc)

short构造函数:CComVariant(short  nSrc)

long 构造函数:CComVariant(long nSrc, VARTYPE=VT_I4)

bool 构造函数:CComVariant(bool  nSrc)

 这个函数有点特别,如果是true,那么boolVal会被赋值为ATL_VARIANT_TRUE,否则,    会被赋值为ATL_VARIANT_FALSE

IDispatch* 构造函数: CComVariant(IDispatch *)

IUnknown*构造函数: CComVariant(IUnknown *)

VARIANT构造函数: CComVariant(const VARIANT *var)

本身构造函数:         CComVariant(const CComVariant & varSrc)

在使用CComVariant(const VARIANT *var)的时候,要注意一定要先初始化var参数,否则会导致 CComVariant被创建为 VT_ERROR

 比如下面的代码, 导致 CComVariant被创建为 VT_ERROR     

    void  fuck()

         {

              VARIANT  vt;

              CComVariant  ccv(&vt);

         }

跟BSTR相关的构造函数:

CComVariant(const CComBSTR & bstrSrc)

CComVariant(LPCOLESTR  lpszSrc)

CComVariant(LPCSTR       lpszSrc)

这三个构造函数,如果不能顺利的构建BSTR内存,那么也会将CComVariant构建为VT_ERROR.

上面三个构造函数,只有第一个能够正确的处理含有NULL的字符串,下面的两个将被NULL给截断,原因就是BSTR的构建过程中,会将NULL当做结束符。 

(2)赋值

赋值跟构造函数类似,也是很多类似的赋值函数。

(3)Clear函数

如果要释放CComVariant,那么需要调用Clear函数,但是在CComVariant的析构函数中,Clear会被自动的调用,所以一般不需要自己去手动调用Clear函数。

(4)Copy函数

Copy将CComVariant的内容,拷贝到一个VARIANT

VARIANT  vt;

long i=5;

CComVariant cvt(i);

cvt.Copy(&vt);

(5)  Detach函数

如果想把CComVariant的实例内容的管理权交给VARIANT管理时,使用Detach函数。这个时候,CComVariant将不再自动管理内容。         

在一个方法里面,如果要用Detach设置一个VARIANT的输出参数时候,记得一定要初始化VARIANT参数,因为在Detach的时候,CComVariant会去销毁清除指定的VARIANT,这个时候,如果VARIANT没有被初始化,那么就很可能会抛出异常。

 void getVariant(VARIANT * poutVar)

         {

             VariantInit(poutVar);//记得一定要初始化VARIANT参数

             //或者

             poutVar->vt=VT_EMPTY;

              //假定ccvar是一个被正确初始化和赋值的CComVariant

             ccvar->Detach(poutVar);

         }

(6) Attach函数

Attach可以让一个CComVariant获得VARIANT的所以权,全面接管所有权。
 

VARIANT  vt;

vt.vt=VT_BSTR;

vt.bstrVal=::SysAllocString("Hello  VARIANT");

CComVariant  ccv;

ccv.Attach(&vt);

这样,CComVariant就接管了 bstr,而 vt不再拥有bstr了,可以不管vt了。

最后,给一个COM方法传递VARIANT,以及从一个方法获得VARIANT
 

//设置

void  SetVar(VARIANT * var)

{

       CComVariant     ccc;

       ccc=var;

       //这里利用的是 VARIANT赋值函数

}

//获得

void  GetVar(VARIANT *  var)

{

    VariantInit(var);

    CComVariant  ccc;

    ccc.Copy(var);

    //或者

    ccc.Detach(var);

}

CComVariant::Attach将 VARIANT 附加到 CComVariant 对象。
CComVariant::ChangeType将 对象 CComVariant 转换为新类型。
CComVariant::Clear清除 CComVariant 对象。
CComVariant::Copy将 VARIANT 复制到 CComVariant 对象。
CComVariant::CopyTo复制 对象 CComVariant 的内容。
CComVariant::Detach从 对象 VARIANT 分离基础 CComVariant 。
CComVariant::GetSize返回对象内容的大小(以字节 CComVariant 数为单位)。
CComVariant::ReadFromStream从流中加载 VARIANT
CComVariant::SetByRef初始化 对象 CComVariant ,将 vt 成员设置为 VT_BYREF 。
CComVariant::WriteToStream将基础 VARIANT 保存到流。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值