Сущность технологии СОМ. Библиотека программиста

ОглавлениеДобавить в закладки К обложке

VT_BSTR BSTR

VT_DISPATCH IDispatch *

VT_ERROR HRESULT

VT_BOOL VARIANT_BOOL (True=-1, False=0)

VT_VARIANT VARIANT *

VT_UNKNOWN IUnknown *

VT_DECIMAL 16 byte fixed point

VT_UI1 opaque byte

Следующие два флага можно использовать в сочетании с вышеприведенными тегами, чтобы указать, что данный вариант (variant) содержит ссылку или массив данного типа:

VT_ARRAY Указывает, что вариант содержит массив SAFEARRAY

VT_BYREF Указывает, что вариант является ссылкой

СОМ предлагает несколько API-функций для управления VARIANT:

// initialize a variant to empty

// обнуляем вариант

void VariantInit(VARIANTARG * pvarg);

// release any resources held in a variant

// освобождаем все ресурсы, используемые в варианте

HRESULT VariantClear(VARIANTARG * pvarg);

// deep-copy one variant to another

// полностью копируем один вариант в другой

HRESULT VariantCopy(VARIANTARG * plhs, VARIANTARG * prhs);

// dereference and deep-copy one variant into another

// разыменовываем и полностью копируем один вариант в другой

HRESULT VariantCopyInd(VARIANT * plhs, VARIANTARG * prhs);

// convert a variant to a designated type

// преобразуем вариант к указанному типу

HRESULT VariantChangeType(VARIANTARG * plhs, VARIANTARG * prhs, USHORT wFlags, VARTYPE vtlhs);

// convert a variant to a designated type

// преобразуем вариант к указанному типу (с явным указанием кода локализации)

HRESULT VariantChangeTypeEx(VARIANTARG * plhs, VARIANTARG * prhs, LCID lcid, USHORT wFlags, VARTYPE vtlhs);

Эти функции значительно упрощают управление VARIANT'ами. Чтобы понять, как используются эти API-функции, рассмотрим метод, принимающий VARIANT в качестве [in]-параметра:

HRESULT UseIt([in] VARIANT var);

Следующий фрагмент кода демонстрирует, как передать в этот метод целое число:

VARIANT var;

VariantInit(&var);

// initialize VARIANT

// инициализируем VARIANT

V_VT(&var) = VT_I4;

// set discriminator

// устанавливаем дискриминатор

V_I4(&var) = 100;

// set union

// устанавливаем объединение

HRESULT hr = pItf->UseIt(var);

// use VARIANT

// используем VARIANT

VariantClear(&var);

// free any resources in VARIANT

// освобождаем все ресурсы VARIANT

Отметим, что этот фрагмент кода использует макросы стандартного аксессора (accessor) для доступа к элементам данных VARIANT. Две следующие строки

V_VT(&var) = VT_I4;

V_I4(&var) = 100;

эквивалентны коду, который обращается к самим элементам данных:

var.vt = VT_I4;

var.lVal = 100;

Первый вариант предпочтительнее, так как он может компилироваться на С-трансляторах, которые не поддерживают неименованных объединений.

Ниже приведен пример того, как с помощью приведенной выше технологии реализация метода использует параметр VARIANT в качестве строки:

STDMETHODIMP MyClass::UseIt( /*[in] */ VARIANT var)

{

// declare and init a second VARIANT

// объявляем и инициализируем второй VARIANT

VARIANT var2;

VariantInit(&var2);

// convert var to a BSTR and store it in var2

// преобразуем переменную в BSTR и заносим ее в var2

HRESULT hr = VariantChangeType(&var2, &var, 0, VT_BSTR);

// use the string

// используем строку

if (SUCCEEDED(hr))

{

ustrcpy(m_szSomeDataMember, SAFEBSTR(V_BSTR(&var2)));

// free any resources held by var2

// освобождаем все ресурсы, поддерживаемые var2

VariantClear(&var2);

}

return hr;

}

Отметим, что API-процедура VariantChangeType способна осуществлять сложное преобразование любого переданного клиентом типа из VARIANT в нужный тип (в данном случае BSTR).

Один из последних типов данных, который вызывает дискуссию, – это интерфейс СОМ. Интерфейсы СОМ могут быть переданы в качестве параметров метода одним из двух способов. Если тип интерфейсного указателя известен на этапе проектирования, то тип интерфейса может быть объявлен статически:

HRESULT GetObject([out] IDog **ppDog);

Если же тип на этапе проектирования неизвестен, то разработчик интерфейса может дать пользователю возможность задать тип на этапе выполнения. Для поддержки динамически типизируемых интерфейсов в IDL имеется атрибут [iid_is]:


Логин
Пароль
Запомнить меня