_variant_t数据类型vt类型意义指南 - 小众知识

_variant_t数据类型vt类型意义指南

2015-08-13 08:54:11 苏内容
  标签: Variant/变量
阅读:4071

_variant_t类封闭了VARIANT数据类型,VARIANT是一个结构体类型,我们可以看一下它的定义
_variant_t是一个类,是VARIANT的完全包装类,它提供多种构造函数和数据转换函数。它继承自一个结构体,其结构如下:
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;
};

其中,vt表示的是_variant_t的数据类型,它的取值是以下枚举结构的值:
enum VARENUM
{
VT_EMPTY  = 0           [V]   [P]     nothing
VT_NULL  =1            [V]   [P]     SQL style Null
VT_I2  =2              [V][T][P][S]  2 byte signed int
VT_I4  =3            [V][T][P][S]  4 byte signed int
VT_R4  = 4              [V][T][P][S]  4 byte real
VT_R8  = 5             [V][T][P][S]  8 byte real
VT_CY  = 6             [V][T][P][S]  currency
VT_DATE  =7           [V][T][P][S]  date
VT_BSTR  =8           [V][T][P][S]  OLE Automation string
VT_DISPATCH =9         [V][T][P][S]  IDispatch *
VT_ERROR  =10          [V][T][P][S]  SCODE
VT_BOOL  =11           [V][T][P][S]  True=-1, False=0
VT_VARIANT  =12        [V][T][P][S]  VARIANT *
VT_UNKNOWN  =13        [V][T]   [S]  IUnknown *
VT_DECIMAL  =14        [V][T]   [S]  16 byte fixed point
VT_RECORD   =36        [V]   [P][S]  user defined type
VT_I1  = 16             [V][T][P][s]  signed char
VT_UI1 =17             [V][T][P][S]  unsigned char
VT_UI2 =18             [V][T][P][S]  unsigned short
VT_UI4  =19            [V][T][P][S]  unsigned short
VT_I8   =20               [T][P]     signed 64-bit int
VT_UI8  =21               [T][P]     unsigned 64-bit int
VT_INT  =22            [V][T][P][S]  signed machine int
VT_UINT  =23           [V][T]   [S]  unsigned machine int
VT_VOID   =24             [T]        C style void
VT_HRESULT  =25           [T]        Standard return type
VT_PTR   =26              [T]        pointer type
VT_SAFEARRAY =27          [T]        (use VT_ARRAY in VARIANT)
VT_CARRAY  = 28            [T]        C style array
VT_USERDEFINED =29        [T]        user defined type
VT_LPSTR  = 30             [T][P]     null terminated string
VT_LPWSTR  =31            [T][P]     wide null terminated string
VT_FILETIME  = 64             [P]     FILETIME
VT_BLOB  = 65                 [P]     Length prefixed bytes
VT_STREAM   =66               [P]     Name of the stream follows
VT_STORAGE  =67              [P]     Name of the storage follows
VT_STREAMED_OBJECT  =68       [P]     Stream contains an object
VT_STORED_OBJECT  =69        [P]     Storage contains an object
VT_BLOB_OBJECT   =70         [P]     Blob contains an object
VT_CF   = 71                  [P]     Clipboard format
VT_CLSID   =72               [P]     A Class ID
VT_VECTOR  = 0x1000            [P]     simple counted array
VT_ARRAY  = 0x2000          [V]           SAFEARRAY*
VT_BYREF  = 0x4000          [V]           void* for local use
VT_BSTR_BLOB =0xfff                     Reserved for system use
VT_RESERVED     = 0x8000,
VT_ILLEGAL = 0xffff,
VT_ILLEGALMASKED = 0xfff,
VT_TYPEMASK    = 0xfff
};
_variant_t变量初始化调用的是_variant_t的构造函数,如果用一个int型的变量对数字类的变量进行初始化,会出错,因为_variant_t的构造函数中没用用整型对其初始化的构造函数,可先将整型转化成long对其进行初始化,赋值操作与构造函数类似,也可如下操作:
int a = 2000;
_variant_t var;
var.vt = VT_I2;
var.lVal = a;
 对于没有构造函数的数据类型都可以这样赋值。
对于有构造函数的就可以直接利用构造函数赋值,例如:
long  l=222; 
_variant_t lVal(l);


vt用来存储存储变量的类型,联合体用来存储对用类型的值

对_variant_t变量初始化调用的是_variant_t的构造函数,我们一般习惯于用一个int型的变量对数字类的变量进行初始化,这对_variant_t变量是不允许的,原因很简单,_variant_t的构造函数中没用用整型对其初始化的构造函数,可先将整型转化成long对其进行初始化,赋值操作与构造函数类似.

_variant_t与CString之间的转化

CString--->_variant_t
CString   str;  
_variant_t   str1=(LPCTSTR)str;
_variant_t--->CString
_variant_t vt;
CString tempstr=(LPCSTR)_bstr_t(vt);


我们先看看COM所支持的一些类型的基本类:

(微软提供,在comdef.h中定义)

在COM中使用的标准类Class如下所示:

_bstr_t:对BSTR类型进行打包,并提供有用的操作和方法;

_com_error:定义抛出的error对象;

_com_ptr_t:封装COM接口指针

_variant_t:对VARIANT类型进行打包,并提供有用的操作和方法;

一、_variant_t类的简单介绍:

_variant_t对象封装了VARIANT数据类型。

The class manages resource allocation and deallocation and makes function calls to VariantInit and VariantClear as appropriate.

(1) _variant类提供的方法:

1> 构造函数

_variant_t
对_variant_t变量初始化调用的是_variant_t的构造函数。我们一般习惯于用一个int型的变量对数字类的变量进行初始化,这对_variant_t变量是不允许的。

原因很简单,_variant_t 的构造函数中没有用整型( Int )对其初始化的构造函数

可先将整型转化成long,然后再对其进行初始化

2> Attach()
Attaches a VARIANT object into the _variant_t object.

3> Clear()

Clears the encapsulated VARIANT object.

4> ChangeType

Changes the type of the _variant_t object to the indicated VARTYPE.

5> Detach

Detaches the encapsulated VARIANT object from this _variant_t object.

6> SetString

将一个string赋值给_variant_t对象;

7> Operators

赋值操作,给现有的_variant_t对象赋一个新值;
8> operator ==, !=

对比两个 _variant_t 对象是否相等;

9> Extractors

Extract data from the encapsulated VARIANT object.

(2) _variant_t的定义:

_variant_t类封闭了VARIANT数据类型,VARIANT是一个结构体类型,我们可以看一下它的定义

[cpp] view plaincopy
typedef struct tagVARIANT  

    VARTYPE vt;                             //存储数据类型 
    unsigned short wReserved1; 
    unsigned short wReserved2; 
    unsigned short wReserved3; 
    union  
    { 
        Byte bVal;                          // VT_UI1. 
        Short iVal;                         // VT_I2. 
        long lVal;                          // VT_I4. 
        float fltVal;                       // VT_R4. 
        double dblVal;                      // VT_R8. 
        VARIANT_BOOL boolVal;               // VT_BOOL. 
        SCODE scode;                        // VT_ERROR. 
        CY cyVal;                           // VT_CY. 
        DATE date;                          // VT_DATE. 
        BSTR bstrVal;                       // VT_BSTR. 
        DECIMAL FAR* pdecVal                // VT_BYREF|VT_DECIMAL. 
        IUnknown FAR* punkVal;              // VT_UNKNOWN. 
        IDispatch FAR* pdispVal;            // VT_DISPATCH. 
        SAFEARRAY FAR* parray;              // VT_ARRAY|*. 
        Byte FAR* pbVal;                    // VT_BYREF|VT_UI1. 
        short FAR* piVal;                   // VT_BYREF|VT_I2. 
        long FAR* plVal;                    // VT_BYREF|VT_I4. 
        float FAR* pfltVal;                 // VT_BYREF|VT_R4. 
        double FAR* pdblVal;                // VT_BYREF|VT_R8. 
        VARIANT_BOOL FAR* pboolVal;         // VT_BYREF|VT_BOOL. 
        SCODE FAR* pscode;                  // VT_BYREF|VT_ERROR. 
        CY FAR* pcyVal;                     // VT_BYREF|VT_CY. 
        DATE FAR* pdate;                    // VT_BYREF|VT_DATE. 
        BSTR FAR* pbstrVal;                 // VT_BYREF|VT_BSTR. 
        IUnknown FAR* FAR* ppunkVal;        // VT_BYREF|VT_UNKNOWN. 
        IDispatch FAR* FAR* ppdispVal;      // VT_BYREF|VT_DISPATCH. 
        SAFEARRAY FAR* FAR* pparray;        // VT_ARRAY|*. 
        VARIANT FAR* pvarVal;               // VT_BYREF|VT_VARIANT. 
        void FAR* byref;                    // Generic ByRef. 
        char cVal;                          // VT_I1. 
        unsigned short uiVal;               // VT_UI2. 
        unsigned long ulVal;                // VT_UI4. 
        int intVal;                         // VT_INT. 
        unsigned int uintVal;               // VT_UINT. 
        char FAR * pcVal;                   // VT_BYREF|VT_I1. 
        unsigned short FAR * puiVal;        // VT_BYREF|VT_UI2. 
        unsigned long FAR * pulVal;         // VT_BYREF|VT_UI4. 
        int FAR * pintVal;                  // VT_BYREF|VT_INT. 
        unsigned int FAR * puintVal;        //VT_BYREF|VT_UINT. 
    }; 
}; 
注意:vt用来存储内部变量(联合体中保存的变量)的类型,联合体用来存储对应类型的值
二、数据类型转换

_bstr_t类可以作为_variant_t类与基本数据类型转换的中介

(1) _variant_t与CString之间的转化

1> CString转换为_variant_t:

[cpp] view plaincopy
CString str; 
_variant_t str1=(LPCTSTR)str;  
使用_variant_t的成员函数SetString来对_variant_t的对象赋值会更好;
2> _variant_t转换为CString:

[cpp] view plaincopy
_variant_t vt; 
CString tempstr=(LPCSTR)_bstr_t(vt);         //_bstr_t的构造函数有对_variant_t类型的处理 
(2) _variant_t与char *之间的转换

1> char * 转换为_variant_t

方法与CString转换为_variant_t的方法类似:

[cpp] view plaincopy
char * cValue; 
_variant_t vValue=(LPSTR)cValue; 
2> _variant_t转换为char *:
错误方法:

[cpp] view plaincopy
_variant_t vValue; 
char * value=(LPSTR)(LPCSTR)_bstr_t(vValue) 
value指向一堆乱码...

原因:不能用char *直接指向(LPSTR)(LPCSTR)_bstr_t( _variant_t ),因为这样转换之后实际上是一个string,而非一个char *
正确方法:

进行转换时,只能用strcpy(),将LPSTR指向的字符复制到char * 所指向的内存中;
如下例:

[cpp] view plaincopy
_variant_t vValue; 
char cValue[16]={0}; 
strcpy(cValue, (LPCSTR)_bstr_t(vValue)); 
(3) 判断_variant_t的值类型

下面的转换代码根据_variant_t的vt进行类型判断,然后将数据值转换为CString类型(可作为转换为其他数据类型的中介)

[cpp] view plaincopy
CString str; 
 
//以下代码演示如何转换为C标准字符串型 
switch(var.vt) 

    case VT_BSTR: 
    { 
        str=var.bstrVal; 
        break; 
    } 
    case VT_I2: //var is short int type  
    { 
        str.Format("%d",(int)var.iVal); 
        break; 
    } 
    case VT_I4: //var is long int type 
    { 
        str.Format("%d", var.lVal); 
        break; 
    } 
    case VT_R4: //var is float type 
    { 
        str.Format("%10.6f", (double)var.fltVal); 
        break; 
    } 
    case VT_R8: //var is double type 
    { 
        str.Format("%10.6f", var.dblVal); 
        break; 
    } 
    case VT_CY: //var is CY type 
    { 
        str=COleCurrency(var).Format(); 
        break; 
    } 
    case VT_DATE: //var is DATE type 
    { 
        str=COleDateTime(var).Format(); 
        break; 
    } 
    case VT_BOOL: //var is VARIANT_BOOL 
    { 
        str= (var.boolVal==0) ?"FALSE": "TRUE"; 
        break; 
    } 
    default: 
    { 
        str.Format("Unk type %d\n",var.vt); 
        TRACE("Unknown type %d\n",var.vt); 
        break; 
    } 

扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1