_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;
}
}