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

/* массив из 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:

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);

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных