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

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

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

FADF_FIXEDSIZE

/* may not be resized or reallocated */

/* не может изменить размеры или быть перемещен*/

FADF_BSTR

/* an array of BSTRs */

/* массив из BSTR */

FADF_UNKNOWN

/* an array of IUnknown* */

/* массив из IUnknown* */

FADF_DISPATCH

/* an array of IDispatch* */

/* массив из IDispatch* */

FADF_VARIANT

/* an array of VARIANTS */

/* массив из VARIANTS */

Для предоставления SAFEARRAY возможности определять типы данных своих элементов, компилятор IDL распознает специальный, специфический для SAFEARRAY, синтаксис:

HRESULT Method([in] SAFEARRAY(type) *ppsa);

где type – тип элемента в SAFEARRAY. Соответствующий прототип данного метода в C++ выглядел бы примерно так:

HRESULT Method(SAFEARRAY **psa);

Отметим, что в определении IDL используется только один уровень косвенности; в то же время в соответствующем определении C++ используются два уровня косвенности. Рассмотрим следующее определение на IDL, задающее массив типа SAFEARRAY из коротких целых чисел:

HRESULT Method([in] SAFEARRAY(short) *psa);

Соответствующее определение на Visual Basic выглядело бы таким образом:

Sub Method(ByVal psa As Integer())

Отметим, что в варианте на Visual Basic не указано явно размерностей массива. Напомним, однако, что Visual Basic поддерживает массивы с фиксированной длиной.

Тип данных SAFEARRAY поддерживается весьма богатым набором API-функций, которые позволяют изменять размерность массивов и производить обход их содержимого переносимым образом. Для доступа к элементам типа SAFEARRAY СОМ предусматривает следующие вызовы API-функций:

// get a pointer to the actual array elements

// получаем указатель на фактически элементы массива

HRESULT SafeArrayAccessData([in] SAFEARRAY *psa, [out] void ** ppv);

// release pointer returned by SafeArrayAccessData

// освобождаем указатель, возвращенный функцией SafeArrayAccessData

HRESULT SafeArrayUnaccessData([in] SAFEARRAY *psa);

// Get number of dimensions

// Получаем количество измерений

ULONG SafeArrayGetDim([in] SAFEARRAY *psa);

// Get upper bound of a dimension

// Получаем верхнюю границу измерения

HRESULT SafeArrayGetUBound([in] SAFEARRAY *psa, [in] UINT nDim, [out] long *pUBound);

// Get lower bound of a dimension

// Получаем нижнюю границу измерения

HRESULT SafeArrayGetLBound([in] SAFEARRAY *psa, [in] UINT nDim, [out] long *pLBound);

Эти методы обеспечивают компактный и надежный способ доступа к текущему содержимому массива. Рассмотрим следующий код на IDL:

HRESULT Sum([in] SAFEARRAY(long) *ppsa, [out, retval] long *pSum);

Тогда следующая реализация метода будет вычислять сумму элементов массива типа SAFEARRAY, состоящего из длинных целых чисел (long integers):

STDMETHODIMP MyClass::Sum(SAFEARRAY **ppsa, long *pnSum)

{

assert(ppsa && *ppsa && pnSum);

assert(SafeArrayGetDim(*ppsa) == 1);

long iUBound, iLBound;

// note that dimension indices are one-based

// отметим, что индексы размерности начинаются с единицы

HRESULT hr = SafeArrayGetUBound(*ppsa, 1, &iUBound);

assert(SUCCEEDED(hr));

hr = SafeArrayGetLBound(*ppsa, 1, &iLBound);

assert(SUCCEEDED(hr));

long *prgn = 0;

hr = SafeArrayAccessData(*ppsa, (void**)&prgn);

*pnSum = 0;

for (long i = 0; i < iUBound – iLBound; i++)

*pnSum += prgn[i];

SafeArrayUnaccessData(*ppsa);

return S_OK;

}

Отметим, что вызовы любых API-функций, которые имеют дело с размерностями массива, используют индексы, начинающиеся с единицы.

Приведенный выше фрагмент кода просто манипулировал содержимым существующего SAFEARRAY-массива. Для создания одномерного массива типа SAFEARRAY для передачи его в качестве параметра метода в СОМ имеется следующая API-функция, которая выделяет память для структуры SAFEARRAY и элементов этого массива в одном непрерывном блоке памяти:

SAFEARRAY *SafeArrayCreateVector(

[in] VARTYPE vt, // element type

// тип элемента

[in] long iLBound, // index of lower bound

// индекс нижней границы

[in] unsigned int cElems); // # of elements

// число элементов

Кроме того, в СОМ имеются различные функции, предназначенные для размещения многомерных массивов, однако их рассмотрение выходит за рамки данной дискуссии. При таком определении метода на IDL:


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