Страница 3 из 7
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 04 июл 2007, 15:29
Absurd
Romeo писал(а):Позволяет, Absurd. Достаточно создать обычный VBScript массив и передать его в качестве параметра в метод. VBScript Array - это и есть SAFEARRAY. Правда существует одна тонкость: при передаче через COM этот массив пакуется в VARIANT, причём пакуется ещё и по ссылке. Но это не большая проблема. Достаточно продэбажить один раз, чтобы все тонкости работы VBScript Engine стали очевидны.
Возвращал из метода VARIANT содержащий SAFEARRAY каждый из элементов которого был VT_DISPATCH. VBS сцуко нопесал при попытке сделать
что "Объект не является Collection'ом".
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 04 июл 2007, 17:26
Romeo
С возвращением SAFEARRAY я не пробовал. Уверен, что и это можно решить, покапавшись в инете. Всё, что я написал выше, касается передачи VBS Array внутрь COM метода, т.е., по сути, это обратная задача.
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 04 июл 2007, 17:29
Romeo
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 08:49
Ivan093
Привет всем!
Методом научного тыка разобрался и научился возвращать com-объект, не знаю правильно или нет, но работает

Вот так сделал:
Код: Выделить всё
STDMETHODIMP TInterface1Impl::Method1(VARIANT* pVal)
{
try
{
CComObject<TInterface2> *ccom = new CComObject<TInterface2>;
CComVariant tmp(ccom);
return tmp.Detach(pVal);
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IInterface1);
}
return S_OK;
};
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 09:48
Absurd
Ivan093 писал(а):Привет всем!
Методом научного тыка разобрался и научился возвращать com-объект, не знаю правильно или нет, но работает

Вот так сделал:
Код: Выделить всё
STDMETHODIMP TInterface1Impl::Method1(VARIANT* pVal)
{
try
{
CComObject<TInterface2> *ccom = new CComObject<TInterface2>;
CComVariant tmp(ccom);
return tmp.Detach(pVal);
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IInterface1);
}
return S_OK;
};
Я создаю так:
Код: Выделить всё
STDMETHODIMP CRoot::GetStruct(VARIANT* param)
{
HRESULT hr = S_OK;
memset(param, 0, sizeof(*param));
if (!m_elementPtr) {
hr = m_elementPtr.CoCreateInstance(__uuidof(CElement));
}
if (SUCCEEDED(hr)) {
CComPtr<IDispatch> elementDispatch;
hr = m_elementPtr.QueryInterface(&elementDispatch);
if (SUCCEEDED(hr)) {
CComVariant retVal(elementDispatch);
hr = retVal.Detach(param);
}
}
return hr;
}
PS:
m_elementPtr декларироваон так:
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 13:41
Ivan093
А у меня такой вариант почему-то не работает:
hr = m_elementPtr.CoCreateInstance(__uuidof(CElement));
hr получается не равным 0. Почему -- не разобрался...
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 14:10
Ivan093
Спасибо всем за помощь, благодаря которой я быстрее разобрался с топиком. Почему-то эта тема освещена мало (судя по поискам в интернете)... Жили бы вы в моем городе -- поставил бы пива/соку

Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 15:34
Absurd
Ivan093 писал(а):Спасибо всем за помощь, благодаря которой я быстрее разобрался с топиком. Почему-то эта тема освещена мало (судя по поискам в интернете)... Жили бы вы в моем городе -- поставил бы пива/соку
Потому что в этой теме вообще толком никто не разбирается - экзамен по COM/ActiveX на brainbench сдало всего 100 человек.
Например, по моему пониманию [in] параметр должен создаваться вызывающим и удаляться получающим. Но вот если входной VARIANT удалить с помощью деструктора класса CComVariant (не отдетачить значение) или напрямую с помошью VariantClear() то возникает win32 экзепшен.
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 05 июл 2007, 16:11
Romeo
COM идеология подразумевает, что объект должен снимать копии со входных параметров, если ему нужно их хранить и должен создавать копии своих внутренних данных, если он должен отдать из в качестве выходного параметра.
COM объект не имеет право убивать входные параметры: вызывающий код создал их, выхывающий код должен и убить.
Re: Как вернуть из ActiveX-компонента структуру или массив?
Добавлено: 06 июл 2007, 10:31
Absurd
Romeo писал(а):COM объект не имеет право убивать входные параметры: вызывающий код создал их, выхывающий код должен и убить.
Давай на пальцах - в чем заключается удаление варианта содержащего IDispatch? Вызывающий очевидно должен сделать QueryInterface(IID_IDispatch) или AddRef(), увеличив счетчик ссылок на объект на единицу, а получающий - сделать Release() когда интерфейс больше не нужен чтобы не случился Interface Leak. VariantClear() очевидно делает Release если вариант имеет тип VT_UNKNOWN или VT_DISPATCH.