Шаг 157.
Среда программирования Visual C++.
Архитектура СОМ. Диспетчерские интерфейсы. Тип данных VARIANT

    На этом шаге мы рассмотрим структуру, описывающую тип данных VARIANT.

    Тип данных VARIANT определен в файле OAIDL.IDL так:

struct tagVARIANT {
    union {
        struct __tagVARIANT {
            VARTYPE vt;
            WORD    wReserved1;
            WORD    wReserved2;
            WORD    wReserved3;
            union {
                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       */
                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      */
                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;
};

    Структура данных VARIANT содержит два поля (если пренебречь зарезервированными). Поле vt описывает тип данных во втором поле. Объединение позволяет во втором поле размещать данные различных типов. Поэтому имя второго поля изменяется в зависимости от значения поля vt. Константы, которыми задается значение поля vt, указаны в комментарии на соответствующей строке объявления объединения.

    Таким образом, использовать структуры данных VARIANT и VARIANTARG нужно в два приема. Взгляните на такой код:

  long lValue = 555; 
  VARIANT vParam;

  VParam.vt = VT_I4; 
  vParam.lVal = lValue;

    В первой строке содержатся сведения о типе данных. В константе VT_I4 объявлено, что во втором элементе находится переменная типа long. Из определения типа VARIANT видно, что при сохранении значения типа long в структуре данных VARIANTARG второму полю должно быть присвоено имя lVal.

    Использование VARIANT для передачи параметров означает, что языки с нестрогим контролем типов, например VBScript, могут обращаться к методам, реализованным на языках со строгим контролем типов, таких как C++. В методе Invoke() стоит предусмотреть проверку корректности типа значения, инкапсулированного в параметре VARIANT. Если тип верен, то параметр извлекается и передается в метод. В противном случае Invoke() попытается привести значение к правильному типу с помощью API-функции VariantChangeType().

    На следующем шаге мы рассмотрим библиотеки типов.




Предыдущий шаг Содержание Следующий шаг