• C++ VARIANT 学习小记录


    一:为什么会有这个?

      目前,计算机语言有很多(大哥,为什么不能就那么一样呢?),如C++、Java,此外还有JavaScript、VBScript等脚本语言,它们自立门派,各自维护自己的数据类型。 

      C++是一种强类型语言,即C++中的某个变量,在使用时类型已经确定,C++中的变量都会被翻译成准确的内存地址和大小,如果类型不确定是不可能处理的。当使用C++这样强类型的语言来读取数据库或者与其他语言之间来交换数据时,它很有可能不知道获取到的数据的具体类型,这个时候必须借助于变体类型读取数据。VARIANT数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。




    二:VARIANT的定义

      在我的windows C:Program Files (x86)Microsoft SDKsWindowsv7.0AInclude下OAIdl.h有这个东东的定义:

    typedef /* [wire_marshal] */ struct tagVARIANT VARIANT;
    
    struct tagVARIANT
        {
        union 
            {
            struct __tagVARIANT
                {
                VARTYPE vt;
                WORD wReserved1;
                WORD wReserved2;
                WORD wReserved3;
                union 
                    {
                    LONGLONG llVal;
                    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 *punkVal;
                    IDispatch *pdispVal;
                    SAFEARRAY *parray;
                    BYTE *pbVal;
                    SHORT *piVal;
                    LONG *plVal;
                    LONGLONG *pllVal;
                    FLOAT *pfltVal;
                    DOUBLE *pdblVal;
                    VARIANT_BOOL *pboolVal;
                    _VARIANT_BOOL *pbool;
                    SCODE *pscode;
                    CY *pcyVal;
                    DATE *pdate;
                    BSTR *pbstrVal;
                    IUnknown **ppunkVal;
                    IDispatch **ppdispVal;
                    SAFEARRAY **pparray;
                    VARIANT *pvarVal;
                    PVOID byref;
                    CHAR cVal;
                    USHORT uiVal;
                    ULONG ulVal;
                    ULONGLONG ullVal;
                    INT intVal;
                    UINT uintVal;
                    DECIMAL *pdecVal;
                    CHAR *pcVal;
                    USHORT *puiVal;
                    ULONG *pulVal;
                    ULONGLONG *pullVal;
                    INT *pintVal;
                    UINT *puintVal;
                    struct __tagBRECORD
                        {
                        PVOID pvRecord;
                        IRecordInfo *pRecInfo;
                        }     __VARIANT_NAME_4;
                    }     __VARIANT_NAME_3;
                }     __VARIANT_NAME_2;
            DECIMAL decVal;
            }     __VARIANT_NAME_1;
        } ;
    typedef VARIANT *LPVARIANT;
    
    typedef VARIANT VARIANTARG;
    
    typedef VARIANT *LPVARIANTARG;
    variant

    看,就是这个东西。太难看了,下面是一个文件简化的让人看的:

    struct tagVARIANT
    {
        union 
        {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union 
            {
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                DATE date;
                BSTR bstrVal;
                SAFEARRAY *parray;
                VARIANT *pvarVal;
            };
        };
    };
    简化

      VARIANT数据结构包含两个域(如果不考虑保留的域)。vt域描述了第二个域的数据类型。为了使多种类型能够在第二个域中出现,定义了一个联合结构。所以,第二个域的名称随着vt域中输入值的不同而改变。下面是同一个文件的里面的东东,这个东西是vt域可以赋哪些值及这些值代表什么变量类型:

    /* VARIANT STRUCTURE
     *
     *  VARTYPE vt;
     *  WORD wReserved1;
     *  WORD wReserved2;
     *  WORD wReserved3;
     *  union {
     *    LONGLONG       VT_I8
     *    LONG           VT_I4
     *    BYTE           VT_UI1
     *    SHORT          VT_I2
     *    FLOAT          VT_R4
     *    DOUBLE         VT_R8
     *    VARIANT_BOOL   VT_BOOL
     *    SCODE          VT_ERROR
     *    CY             VT_CY
     *    DATE           VT_DATE
     *    BSTR           VT_BSTR
     *    IUnknown *     VT_UNKNOWN
     *    IDispatch *    VT_DISPATCH
     *    SAFEARRAY *    VT_ARRAY
     *    BYTE *         VT_BYREF|VT_UI1
     *    SHORT *        VT_BYREF|VT_I2
     *    LONG *         VT_BYREF|VT_I4
     *    LONGLONG *     VT_BYREF|VT_I8
     *    FLOAT *        VT_BYREF|VT_R4
     *    DOUBLE *       VT_BYREF|VT_R8
     *    VARIANT_BOOL * VT_BYREF|VT_BOOL
     *    SCODE *        VT_BYREF|VT_ERROR
     *    CY *           VT_BYREF|VT_CY
     *    DATE *         VT_BYREF|VT_DATE
     *    BSTR *         VT_BYREF|VT_BSTR
     *    IUnknown **    VT_BYREF|VT_UNKNOWN
     *    IDispatch **   VT_BYREF|VT_DISPATCH
     *    SAFEARRAY **   VT_BYREF|VT_ARRAY
     *    VARIANT *      VT_BYREF|VT_VARIANT
     *    PVOID          VT_BYREF (Generic ByRef)
     *    CHAR           VT_I1
     *    USHORT         VT_UI2
     *    ULONG          VT_UI4
     *    ULONGLONG      VT_UI8
     *    INT            VT_INT
     *    UINT           VT_UINT
     *    DECIMAL *      VT_BYREF|VT_DECIMAL
     *    CHAR *         VT_BYREF|VT_I1
     *    USHORT *       VT_BYREF|VT_UI2
     *    ULONG *        VT_BYREF|VT_UI4
     *    ULONGLONG *    VT_BYREF|VT_UI8
     *    INT *          VT_BYREF|VT_INT
     *    UINT *         VT_BYREF|VT_UINT
     *  }
     */
    类型标识



    三:使用例子

      看一个小例子就知道怎么用了:

    #include <iostream>
    #include <OAIdl.h>
    
    using namespace std;
    
    int main(void)
    {
        VARIANT var;
        cout<<sizeof(VARIANT)<<endl;
    
        var.vt = VT_BOOL;        //bool
        var.boolVal = true;
        cout<<var.boolVal<<endl;
    
        var.vt = VT_I4;        //long
        var.lVal = 100;
        cout<<var.lVal<<endl;
    
        var.vt = VT_R8;        //double
        var.dblVal = 3.23;
        cout<<var.dblVal<<endl;
    
        cin.get();
    }
    C++例子

    从中可以看到使用时,你要先指定这个variant是个什么玩意儿,然后给那个玩意儿赋值,输出的时候也要输出那个玩意儿的值,乖点总没错。输出:




    四:还有一点

      在使用VARIANT的时候,经常会用到一些它给定的宏,这些宏可以很方便地对VARIANT指定类型及赋值,在我的 C:Program Files (x86)Microsoft SDKsWindowsv7.0AInclude 下的oleauto.h里面就有:

    // Declare variant access functions.
    
    #if __STDC__ || defined(NONAMELESSUNION)
    #define V_UNION(X, Y)   ((X)->n1.n2.n3.Y)
    #define V_VT(X)         ((X)->n1.n2.vt)
    #define V_RECORDINFO(X) ((X)->n1.n2.n3.brecVal.pRecInfo)
    #define V_RECORD(X)     ((X)->n1.n2.n3.brecVal.pvRecord)
    #else
    #define V_UNION(X, Y)   ((X)->Y)
    #define V_VT(X)         ((X)->vt)
    #define V_RECORDINFO(X) ((X)->pRecInfo)
    #define V_RECORD(X)     ((X)->pvRecord)
    #endif
    
    /* Variant access macros
     */
    #define V_ISBYREF(X)     (V_VT(X)&VT_BYREF)
    #define V_ISARRAY(X)     (V_VT(X)&VT_ARRAY)
    #define V_ISVECTOR(X)    (V_VT(X)&VT_VECTOR)
    #define V_NONE(X)        V_I2(X)
    
    #define V_UI1(X)         V_UNION(X, bVal)
    #define V_UI1REF(X)      V_UNION(X, pbVal)
    #define V_I2(X)          V_UNION(X, iVal)
    #define V_I2REF(X)       V_UNION(X, piVal)
    #define V_I4(X)          V_UNION(X, lVal)
    #define V_I4REF(X)       V_UNION(X, plVal)
    #define V_I8(X)          V_UNION(X, llVal)
    #define V_I8REF(X)       V_UNION(X, pllVal)
    #define V_R4(X)          V_UNION(X, fltVal)
    #define V_R4REF(X)       V_UNION(X, pfltVal)
    #define V_R8(X)          V_UNION(X, dblVal)
    #define V_R8REF(X)       V_UNION(X, pdblVal)
    #define V_I1(X)          V_UNION(X, cVal)
    #define V_I1REF(X)       V_UNION(X, pcVal)
    #define V_UI2(X)         V_UNION(X, uiVal)
    #define V_UI2REF(X)      V_UNION(X, puiVal)
    #define V_UI4(X)         V_UNION(X, ulVal)
    #define V_UI4REF(X)      V_UNION(X, pulVal)
    #define V_UI8(X)         V_UNION(X, ullVal)
    #define V_UI8REF(X)      V_UNION(X, pullVal)
    #define V_INT(X)         V_UNION(X, intVal)
    #define V_INTREF(X)      V_UNION(X, pintVal)
    #define V_UINT(X)        V_UNION(X, uintVal)
    #define V_UINTREF(X)     V_UNION(X, puintVal)
    
    #ifdef _WIN64
    #define V_INT_PTR(X)        V_UNION(X, llVal)
    #define V_UINT_PTR(X)       V_UNION(X, ullVal)
    #define V_INT_PTRREF(X)     V_UNION(X, pllVal)
    #define V_UINT_PTRREF(X)    V_UNION(X, pullVal)
    #else
    #define V_INT_PTR(X)        V_UNION(X, lVal)
    #define V_UINT_PTR(X)       V_UNION(X, ulVal)
    #define V_INT_PTRREF(X)     V_UNION(X, plVal)
    #define V_UINT_PTRREF(X)    V_UNION(X, pulVal)
    #endif
    
    #define V_CY(X)          V_UNION(X, cyVal)
    #define V_CYREF(X)       V_UNION(X, pcyVal)
    #define V_DATE(X)        V_UNION(X, date)
    #define V_DATEREF(X)     V_UNION(X, pdate)
    #define V_BSTR(X)        V_UNION(X, bstrVal)
    #define V_BSTRREF(X)     V_UNION(X, pbstrVal)
    #define V_DISPATCH(X)    V_UNION(X, pdispVal)
    #define V_DISPATCHREF(X) V_UNION(X, ppdispVal)
    #define V_ERROR(X)       V_UNION(X, scode)
    #define V_ERRORREF(X)    V_UNION(X, pscode)
    #define V_BOOL(X)        V_UNION(X, boolVal)
    #define V_BOOLREF(X)     V_UNION(X, pboolVal)
    #define V_UNKNOWN(X)     V_UNION(X, punkVal)
    #define V_UNKNOWNREF(X)  V_UNION(X, ppunkVal)
    #define V_VARIANTREF(X)  V_UNION(X, pvarVal)
    #define V_ARRAY(X)       V_UNION(X, parray)
    #define V_ARRAYREF(X)    V_UNION(X, pparray)
    #define V_BYREF(X)       V_UNION(X, byref)
    
    #define V_DECIMAL(X)     V_UNION(X, decVal)
    #define V_DECIMALREF(X)  V_UNION(X, pdecVal)
    
    #ifndef RC_INVOKED
    #include <poppack.h>
    #endif // RC_INVOKED
    
    #endif     // __OLEAUTO_H__
    Variant宏

    同样的目录wtypes.h下也有:

    typedef unsigned short VARTYPE;
    
    /*
     * VARENUM usage key,
     *
     * * [V] - may appear in a VARIANT
     * * [T] - may appear in a TYPEDESC
     * * [P] - may appear in an OLE property set
     * * [S] - may appear in a Safe Array
     *
     *
     *  VT_EMPTY            [V]   [P]     nothing
     *  VT_NULL             [V]   [P]     SQL style Null
     *  VT_I2               [V][T][P][S]  2 byte signed int
     *  VT_I4               [V][T][P][S]  4 byte signed int
     *  VT_R4               [V][T][P][S]  4 byte real
     *  VT_R8               [V][T][P][S]  8 byte real
     *  VT_CY               [V][T][P][S]  currency
     *  VT_DATE             [V][T][P][S]  date
     *  VT_BSTR             [V][T][P][S]  OLE Automation string
     *  VT_DISPATCH         [V][T]   [S]  IDispatch *
     *  VT_ERROR            [V][T][P][S]  SCODE
     *  VT_BOOL             [V][T][P][S]  True=-1, False=0
     *  VT_VARIANT          [V][T][P][S]  VARIANT *
     *  VT_UNKNOWN          [V][T]   [S]  IUnknown *
     *  VT_DECIMAL          [V][T]   [S]  16 byte fixed point
     *  VT_RECORD           [V]   [P][S]  user defined type
     *  VT_I1               [V][T][P][s]  signed char
     *  VT_UI1              [V][T][P][S]  unsigned char
     *  VT_UI2              [V][T][P][S]  unsigned short
     *  VT_UI4              [V][T][P][S]  unsigned long
     *  VT_I8                  [T][P]     signed 64-bit int
     *  VT_UI8                 [T][P]     unsigned 64-bit int
     *  VT_INT              [V][T][P][S]  signed machine int
     *  VT_UINT             [V][T]   [S]  unsigned machine int
     *  VT_INT_PTR             [T]        signed machine register size width
     *  VT_UINT_PTR            [T]        unsigned machine register size width
     *  VT_VOID                [T]        C style void
     *  VT_HRESULT             [T]        Standard return type
     *  VT_PTR                 [T]        pointer type
     *  VT_SAFEARRAY           [T]        (use VT_ARRAY in VARIANT)
     *  VT_CARRAY              [T]        C style array
     *  VT_USERDEFINED         [T]        user defined type
     *  VT_LPSTR               [T][P]     null terminated string
     *  VT_LPWSTR              [T][P]     wide null terminated string
     *  VT_FILETIME               [P]     FILETIME
     *  VT_BLOB                   [P]     Length prefixed bytes
     *  VT_STREAM                 [P]     Name of the stream follows
     *  VT_STORAGE                [P]     Name of the storage follows
     *  VT_STREAMED_OBJECT        [P]     Stream contains an object
     *  VT_STORED_OBJECT          [P]     Storage contains an object
     *  VT_VERSIONED_STREAM       [P]     Stream with a GUID version
     *  VT_BLOB_OBJECT            [P]     Blob contains an object 
     *  VT_CF                     [P]     Clipboard format
     *  VT_CLSID                  [P]     A Class ID
     *  VT_VECTOR                 [P]     simple counted array
     *  VT_ARRAY            [V]           SAFEARRAY*
     *  VT_BYREF            [V]           void* for local use
     *  VT_BSTR_BLOB                      Reserved for system use
     */
    
    enum VARENUM
        {    VT_EMPTY    = 0,
        VT_NULL    = 1,
        VT_I2    = 2,
        VT_I4    = 3,
        VT_R4    = 4,
        VT_R8    = 5,
        VT_CY    = 6,
        VT_DATE    = 7,
        VT_BSTR    = 8,
        VT_DISPATCH    = 9,
        VT_ERROR    = 10,
        VT_BOOL    = 11,
        VT_VARIANT    = 12,
        VT_UNKNOWN    = 13,
        VT_DECIMAL    = 14,
        VT_I1    = 16,
        VT_UI1    = 17,
        VT_UI2    = 18,
        VT_UI4    = 19,
        VT_I8    = 20,
        VT_UI8    = 21,
        VT_INT    = 22,
        VT_UINT    = 23,
        VT_VOID    = 24,
        VT_HRESULT    = 25,
        VT_PTR    = 26,
        VT_SAFEARRAY    = 27,
        VT_CARRAY    = 28,
        VT_USERDEFINED    = 29,
        VT_LPSTR    = 30,
        VT_LPWSTR    = 31,
        VT_RECORD    = 36,
        VT_INT_PTR    = 37,
        VT_UINT_PTR    = 38,
        VT_FILETIME    = 64,
        VT_BLOB    = 65,
        VT_STREAM    = 66,
        VT_STORAGE    = 67,
        VT_STREAMED_OBJECT    = 68,
        VT_STORED_OBJECT    = 69,
        VT_BLOB_OBJECT    = 70,
        VT_CF    = 71,
        VT_CLSID    = 72,
        VT_VERSIONED_STREAM    = 73,
        VT_BSTR_BLOB    = 0xfff,
        VT_VECTOR    = 0x1000,
        VT_ARRAY    = 0x2000,
        VT_BYREF    = 0x4000,
        VT_RESERVED    = 0x8000,
        VT_ILLEGAL    = 0xffff,
        VT_ILLEGALMASKED    = 0xfff,
        VT_TYPEMASK    = 0xfff
        } ;
    枚举等

    在调试的时候看到了这种难看的就按 Alt+G进入源文件看看是干啥的。

      下面是我看到的源码:

     1 DISPAPI KETAPITextBox::Copy( VARIANT *RHS )
     2 {
     3     ASSERT(m_spShape);
     4     VERIFY_IN_POINTER(RHS);
     5 
     6     HRESULT hr = m_spShape->Copy();
     7     V_VT(RHS) = VT_BOOL;
     8     V_BOOL(RHS) = SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE;
     9 
    10     return hr;
    11 }

    从第7行看,V_VT(RHS) = VT_BOOL; 这句话就是把RHS指向的VARIANT的vt值赋成VT的bool类型,其实也就是 RHS->vt = VARIANT的bool 这个意思了,现在这个variant表示bool啦,懂了!

  • 相关阅读:
    ACM-ICPC 2018 徐州赛区网络预赛 I. Characters with Hash
    hdu 5437
    poj 1502
    ACM-ICPC 2018 沈阳赛区网络预赛 K. Supreme Number
    ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph
    ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall
    ACM-ICPC 2018 南京赛区网络预赛 J. Sum
    法里数列
    ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze
    Hashtable 为什么不叫 HashTable?
  • 原文地址:https://www.cnblogs.com/jiayith/p/3865058.html
Copyright © 2020-2023  润新知