Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите с пересылкой массива COM-клиенту, CBuilder не понимает атрибуты IDL? 
:(
    Опции темы
arg
Дата 16.5.2003, 21:58 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Хочу передать из клиента серверу указатель, а сервер должен распределить память, заполнить массив и вернуть. Пользуюсь C++ Builder 5 и его стандартным Type Library Editor. Так вот редактор не дает установить атрибуты указателя, например, [size_is], которые нужны для сообщения маршалеру о размере массива, если я правильно понимаю. Как быть?
  Вверх
Guest_tim
Дата 17.5.2003, 02:22 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


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
Дата 18.5.2003, 21:18 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


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
Дата 19.5.2003, 19:39 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Вот мой код, это метод моего класса по работе с ADO. Этот метод заполняет SAFEARRAY набором данных, полученный от SQL запроса. Суть метода похожа на Ваш. Обратите внимание, как я пакую массив в вариант:
...
//Пакуем массив в VARIANT
V_VT(vtOutRecordsArray) = VT_ARRAY | VT_VARIANT;
V_ARRAY(vtOutRecordsArray) = pSA;
...

И еще одна особенность - я не блокирую SAFEARRAY (SafeArrayLock(psa);), может в этом дело (хотя не должно быть). Попробуйте так запаковать.

Ниже клиентский код по распаковке. Клиентский компонент по отношению к серверному работает с ASP страницей (но не суть важно). На HTML тэги можно не обращать внимания

Такой подход работает (создано лично), если проблемы не исправятся будем думать дальше.
Надеюсь поможет smile.gif

Тим


=========================================================================
На сервере:
=========================================================================

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
Дата 22.5.2003, 18:17 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Большое спасибо, все заработало.
Интересно, а массивы объектов таким способом можно передавать?
  Вверх
Guest_tim
Дата 27.5.2003, 19:53 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Очень рад, что смог помочь smile.gif))

На счет объектов не пробовал, может заработает...

Тим

  Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0664 ]   [ Использовано запросов: 19 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.