Сущность технологии COM



         

Массивы - часть 15


Отметим, что вызовы любых 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:

HRESULT GetPrimes([in] long nStart, [in] long nEnd, [out] SAFEARRAY(long) *ppsa);

следующее определение метода на C++ возвращает вызывающей программе массив типа SAFEARRAY, размещенный в вызываемом методе:

STDMETHODIMP MyClass::GetPrimes (long nMin, long nMax, SAFEARRAY **ppsa) { assert(ppsa); UINT cElems = GetNumberOfPrimes(nMin, nMax); *ppsa = SafeArrayCreateVector(VT_I4, 0, cElems); assert(*ppsa); long *prgn = 0; HRESULT hr = SafeArrayAccessData(*ppsa, (void**)&prgn); assert(SUCCEEDED(hr)); for (UINT i=0; i < cElems; i++) prgn[i] = GetNextPrime(i ? prgn[1 - 1] : nMin); SafeArrayUnaccessData(*ppsa); return S_OK; }

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

Function GetSumOfPrimes(ByVal nMin as Long, ByVal nMax as Long) as Long Dim arr() as Long Dim n as Variant Objref.GetPrimes nMin, nMax, arr GetSumOfPrimes = 0 for each n in arr GetSumOfPrimes = GetSumOfPrimes + n Next n End Function

что соответствует следующему коду на C++:

long GetSumOfPrimes (long nMin, long nMax) { SAFEARRAY *pArray = 0; HRESULT hr = g_pObjRef->GetPrimes(nMin, nMax, &pArray); assert(SUCCEEDED(hr) && SafeArrayGetDim(pArray) == 1); long *prgn = 0; hr = SafeArrayAccessData(pArray, (void**)&prgn); long iUBound, iLBound, result = 0; SafeArrayGetUBound(pArray, 1, &iUBound); SafeArrayGetLBound(pArray, 1, &iLBound); for (long n = iLBound; n <= iUBound: n++) result += prgn[n]; SafeArrayUnaccessData(pArray); SafeArrayDestroy(pArray); return n; }

Отметим, что вызывающая программа ответственна за освобождение ресурсов, выделенных для SAFEARRAY-массива, возвращенного как [out]-параметр. Вызов функции SafeArrayDestroy корректно освобождает всю память и все ресурсы, удерживаемые структурой SAFEARRAY.




Содержание  Назад  Вперед