![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
arg |
|
|||
Unregistered |
Хочу передать из клиента серверу указатель, а сервер должен распределить память, заполнить массив и вернуть. Пользуюсь C++ Builder 5 и его стандартным Type Library Editor. Так вот редактор не дает установить атрибуты указателя, например, [size_is], которые нужны для сообщения маршалеру о размере массива, если я правильно понимаю. Как быть?
|
|||
|
||||
Guest_tim |
|
|||
Unregistered |
Может это и не то, что нужно, но предлагаю вариант:
Я использую VARIANT и его поле parray - указатель на SAFEARRAY. Примерно так: VARIANT *vt; ::CoTaskMemAlloc(sizeof(VARIANT)); ::VariantInit(vt); pComponent->Method(VARIANT *vt); { //Устанавливаем тип указателя на массив VariantChangeType(...vt...); //Массив создаем при помощи функции SafeArrayCreate SAFEARRAY *psa; psa = SafeArrayCreate(...) //Здесь заполняем массив... vt->parray = psa; } Примерно так, конечно несколько строк пропущено, но думаю разберетесь. Если будут проблемы напишу подробнее Тим |
|||
|
||||
arg |
|
|||
Unregistered |
Guest_tim, мне ваш вариант очень понравился. Я сделал так, как понял, но не
получается. Взгляните: На стороне сервера ******************************** STDMETHODIMP TFillStructureImpl::GetArray(VARIANT* parr) { int i; int* psadata; SAFEARRAY *psa; SAFEARRAYBOUND rgsabnd; VariantChangeType(parr,parr,VARIANT_NOVALUEPROP,varInteger); rgsabnd.cElements=5; rgsabnd.lLbound=0; psa = SafeArrayCreate(varInteger,1,&rgsabnd); SafeArrayLock(psa); SafeArrayAccessData(psa,&(void*)psadata); for(i=0;i<5;i++) psadata[i]=i+1; SafeArrayCopy(psa,&(parr->parray)); SafeArrayUnaccessData(psa); SafeArrayUnlock(psa); return S_OK; } ******************************** На стороне клиента ******************************** VARIANT *vt; int *psadata; vt=(VARIANT *)CoTaskMemAlloc(sizeof(VARIANT)); VariantInit(vt); SrvObj->GetArray(vt); SafeArrayLock(vt->parray); SafeArrayAccessData(vt->parray,&(void*)psadata); ... ******************************** на стороне клинета после таких операций в psadata неопределенные значения. Плиз, подскажите, что я сделал не так? |
|||
|
||||
Guest_tim |
|
|||
Unregistered |
Вот мой код, это метод моего класса по работе с ADO. Этот метод заполняет SAFEARRAY набором данных, полученный от SQL запроса. Суть метода похожа на Ваш. Обратите внимание, как я пакую массив в вариант:
... //Пакуем массив в VARIANT V_VT(vtOutRecordsArray) = VT_ARRAY | VT_VARIANT; V_ARRAY(vtOutRecordsArray) = pSA; ... И еще одна особенность - я не блокирую SAFEARRAY (SafeArrayLock(psa);), может в этом дело (хотя не должно быть). Попробуйте так запаковать. Ниже клиентский код по распаковке. Клиентский компонент по отношению к серверному работает с ASP страницей (но не суть важно). На HTML тэги можно не обращать внимания Такой подход работает (создано лично), если проблемы не исправятся будем думать дальше. Надеюсь поможет ![]() Тим ========================================================================= На сервере: ========================================================================= void CSmartADO::FillArrayFromRecordset(VARIANT *vtOutRecordsArray) { if (m_spRecordset) { //Число записей в наборе long lRecordsCount = 0; //Определяем число записей в наборе while (!m_spRecordset->adoEOF) { m_spRecordset->MoveNext(); lRecordsCount++; } if (lRecordsCount > 0) { m_spRecordset->MoveFirst(); } SAFEARRAY *pSA; SAFEARRAYBOUND aDim[2]; aDim[0].lLbound = 0; aDim[0].cElements = lRecordsCount + 1; //Помимо строк заносим еще и имена полей, поэтому + 1 aDim[1].lLbound = 0; aDim[1].cElements = m_spRecordset->GetFields()->GetCount(); //По числу полей в наборе long l[2]; int i, j; _variant_t vt; //Создаем массив pSA = SafeArrayCreate(VT_VARIANT, 2, aDim); if (pSA) { //Заносим в первую строку массива имена полей из набора for (i = 0; i < m_spRecordset->GetFields()->GetCount(); i++) { l[0] = 0; l[1] = i; vt = m_spRecordset->GetFields()->GetItem((CComVariant)i)->GetName(); SafeArrayPutElement(pSA, l, &vt); } j = 1; //Пробегаем по всем записям и заносим их в массив while (!m_spRecordset->adoEOF) { for (i = 0; i < m_spRecordset->GetFields()->GetCount(); i++) { l[0] = j; l[1] = i; vt = m_spRecordset->GetFields()->GetItem((CComVariant)i)->GetValue(); SafeArrayPutElement(pSA, l, &vt); } j++; m_spRecordset->MoveNext(); } } else { throw; } //Удаляем набор данных (больше он не нужен, т.к. данные в массиве) m_spRecordset->Close(); m_spRecordset.Release(); //Пакуем массив в VARIANT V_VT(vtOutRecordsArray) = VT_ARRAY | VT_VARIANT; V_ARRAY(vtOutRecordsArray) = pSA; } else { //Возвращаем пустой указатель V_VT(vtOutRecordsArray) = VT_ARRAY | VT_VARIANT; V_ARRAY(vtOutRecordsArray) = NULL; //throw; } } ========================================================================= На клиенте: ========================================================================= void CCertificate::DrawCalculations(VARIANT *pvtArray) { HRESULT hr; SAFEARRAY *psa = NULL; LONG lLBound1, lUBound1, lLBound2, lUBound2; LONG lInd[2]; VARIANT vtValue; //Присваиваем указатель на SAFEARRAY в переменную psa из варианта psa = pvtArray->parray; //m_pIResponse->Write((_variant_t)"Определение границ массива...<BR>"); //Узнаем границы массива SafeArrayGetLBound(psa, 1, &lLBound1); SafeArrayGetUBound(psa, 1, &lUBound1); SafeArrayGetLBound(psa, 2, &lLBound2); SafeArrayGetUBound(psa, 2, &lUBound2); //m_pIResponse->Write((_variant_t)"Обход массива...<BR>"); //Производим отображение данных m_pIResponse->Write((_variant_t)"<TABLE border=2>"); for (LONG i = lLBound1; i <= lUBound1; i++) { m_pIResponse->Write((_variant_t)"<TR>"); for (LONG j = lLBound2; j <= lUBound2; j++) { lInd[0] = i; lInd[1] = j; hr = SafeArrayGetElement(psa, lInd, &vtValue); if (FAILED(hr)) _com_issue_error(hr); m_pIResponse->Write((_variant_t)"<TD>"); m_pIResponse->Write(vtValue); m_pIResponse->Write((_variant_t)"</TD>"); } m_pIResponse->Write((_variant_t)"</TR>"); } m_pIResponse->Write((_variant_t)"</TABLE>"); //m_pIResponse->Write((_variant_t)"Удаление массива...<BR>"); //Не забываем удалить массив (SmartADOComponent - создает, а здесь - удаляем) hr = SafeArrayDestroy(psa); if (FAILED(hr)) _com_issue_error(hr); } |
|||
|
||||
arg |
|
|||
Unregistered |
Большое спасибо, все заработало.
Интересно, а массивы объектов таким способом можно передавать? |
|||
|
||||
Guest_tim |
|
|||
Unregistered |
Очень рад, что смог помочь
![]() На счет объектов не пробовал, может заработает... Тим |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |