Получение результата с помощью Invoke
От: ddd329  
Дата: 12.01.11 15:04
Оценка:
Привет всем!!! Вот изучаю COM технологию по книге Дейла Роджерсона — "Основы COM", разбираю пример с дуальным интерфейсом.
Имеется интерфейс IOperation, который содержит следующую функцию:
HRESULT __stdcall CMath::Summa(long fp_a, long fp_b, long* fp_c)
{
*fp_c = fp_a + fp_b ;
return S_OK ;
}
Если пользуюсь интерфейсом через vtbl, то все нормально, а вот если через IDispatch, то че-то не могу получить результат.
Во-первых: результат должен быть получен так же через третий параметр метода Summa, или же через 6-ой параметр метода Invoke???
На сервере Invoke реализована так:
HRESULT __stdcall CMath::Invoke(
DISPID dispidMember,
const IID& iid,
LCID, // Localization is not supported.
WORD wFlags,
DISPPARAMS* pDispParams,
VARIANT* pvarResult,
EXCEPINFO* pExcepInfo,
UINT* pArgErr)
{
if (iid != IID_NULL)
{
return DISP_E_UNKNOWNINTERFACE ;
}

::SetErrorInfo(0, NULL) ;

HRESULT hr = m_pITypeInfo->Invoke( //pITypeLib->GetTypeInfoOfGuid(IID_IOperation,&m_pITypeInfo) ;
static_cast<IDispatch*>(this),
dispidMember, wFlags, pDispParams,
pvarResult, pExcepInfo, pArgErr) ;
return hr ;
}
//------------------------------------------------------------------------------------------------------------------------
На клиенте код вызова такой:
OleInitialize(NULL);
HRESULT hr;
wchar_t progid[] = L"SERVER_COM.Math";
CLSID clsid;
hr = CLSIDFromProgID(progid,&clsid);
IDispatch *pIDispatch = NULL;

IOperation* pIOperation = NULL ;
hr = CoCreateInstance(clsid,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IDispatch,
(void**)&pIDispatch) ;

DISPID dispid;
OLECHAR *name = L"Summa";

hr = pIDispatch->GetIDsOfNames(IID_NULL,
&name,
1,
GetUserDefaultLCID(),
&dispid
);

unsigned int c = 0;//третий параметр Summa, через который должен быть возвращен результат

VARIANTARG *v_arg = new VARIANTARG [3];
VariantInit(&v_arg[0]);
VariantInit(&v_arg[1]);
VariantInit(&v_arg[2]);
v_arg[0].vt = VT_UINT;
v_arg[0].uintVal = 5;
v_arg[1].vt = VT_UINT;
v_arg[1].uintVal = 7;
v_arg[2].vt = VT_BYREF|VT_UINT;
v_arg[2].puintVal = &c;

VARIANTARG v_res;
VariantInit(&v_res);

DISPPARAMS dispparams = {v_arg,
NULL,
3,
0};

hr = pIDispatch->Invoke(dispid,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_METHOD,
&dispparams,
&v_res,
NULL,
NULL
);
..............................................................
OleUninitialize() ;
//----------------------------------------------------------------------------------------------------------
Результаты такие:
1) v_res.vt == VT_EMPTY
2) c == 0
ВОПРОС: Как получить результат суммы???
Re: Получение результата с помощью Invoke
От: Vi2 Удмуртия http://www.adem.ru
Дата: 12.01.11 18:23
Оценка: 2 (1)
Здравствуйте, ddd329, Вы писали:

D>Если пользуюсь интерфейсом через vtbl, то все нормально, а вот если через IDispatch, то че-то не могу получить результат.

D>Во-первых: результат должен быть получен так же через третий параметр метода Summa, или же через 6-ой параметр метода Invoke???

Это зависит от описания параметров метода. Если параметр не имеет атрибута [retval], то он может быть получен через третий параметр метода Summa. Если же имеет, то только через 6-ой параметр метода Invoke (причем метод Summa должен получить только два параметра).

D>Результаты такие:

D>1) v_res.vt == VT_EMPTY
D>2) c == 0
D>ВОПРОС: Как получить результат суммы???

Нужно также смотреть на код возврата hr. У тебя он сейчас содержит код ошибки, указывающий на характер ошибочных действий. Что помогло бы тебе в анализе причин.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Получение результата с помощью Invoke
От: Аноним  
Дата: 13.01.11 09:06
Оценка:
hr — не содержит ошибок, я проверял
Re[3]: Получение результата с помощью Invoke
От: Vi2 Удмуртия http://www.adem.ru
Дата: 13.01.11 11:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>hr — не содержит ошибок, я проверял


Тогда давай описание класса CMath или как там реализован CMath::Invoke.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Получение результата с помощью Invoke
От: ddd329  
Дата: 13.01.11 11:51
Оценка:
Я же привел код как реализован CMath::Invoke.
Re[5]: Получение результата с помощью Invoke
От: Vi2 Удмуртия http://www.adem.ru
Дата: 13.01.11 12:14
Оценка:
Здравствуйте, ddd329, Вы писали:

D>Я же привел код как реализован CMath::Invoke.


Да, пропустил. Тогда непонятно, что "hr — не содержит ошибок, я проверял". Должен возвращаться код ошибки несоответствия параметров или числа параметров.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re: Получение результата с помощью Invoke
От: Vi2 Удмуртия http://www.adem.ru
Дата: 13.01.11 12:19
Оценка:
Здравствуйте, ddd329, Вы писали:

D>    HRESULT hr = m_pITypeInfo->Invoke(  //pITypeLib->GetTypeInfoOfGuid(IID_IOperation,&m_pITypeInfo) ;
D>        static_cast<IDispatch*>(this),
D>        dispidMember, wFlags, pDispParams,
D>        pvarResult, pExcepInfo, pArgErr) ;
D>    return hr ;


Попробуй кастировать к IOperation*, а не к IDispatch*, ведь туда нужно передавать адрес описываемого интерфейса.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Получение результата с помощью Invoke
От: Аноним  
Дата: 14.01.11 12:11
Оценка:
А правильно ли я указываю третий параметр Summa? Который на сервере описан как: Summa(long fp_a, long fp_b, long* fp_c);
v_arg[2].vt = VT_BYREF|VT_UINT;
v_arg[2].puintVal = &c;
Re[3]: Получение результата с помощью Invoke
От: Vi2 Удмуртия http://www.adem.ru
Дата: 14.01.11 12:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А правильно ли я указываю третий параметр Summa? Который на сервере описан как: Summa(long fp_a, long fp_b, long* fp_c);

А>v_arg[2].vt = VT_BYREF|VT_UINT;
А>v_arg[2].puintVal = &c;

Это зависит от описания метода в IDL файле. Поскольку IOperation — дуальный интерфейс:
[object, dual, ...]
interface IOperation : IDispatch {
[id(1)] HRESULT Summa([in] long fp_a, [in] long fp_b, [in,out] long* fp_c);     //***1***
[id(1)] HRESULT Summa([in] long fp_a, [in] long fp_b, [out,retval] long* fp_c); //***2***
...

Первое описание (***1***) требует передачи трёх параметров, а второе (***2***) — только двух. Что видно при эквивалентном описании dispinterface:
[...]
dispinterface _Operation {
methods:
[id(1)] void Summa([in] long fp_a, [in] long fp_b, [in,out] long* fp_c); //***1***
[id(1)] long Summa([in] long fp_a, [in] long fp_b);                      //***2***
...
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Получение результата с помощью Invoke
От: ddd329  
Дата: 14.01.11 16:02
Оценка:
Спасибо, ещё попробую че-нибудь. А можно вопрос не в тему, где можно черпать инфу о COM, может какие-нибудь журналы выходят и т.д.
Re[4]: Получение результата с помощью Invoke
От: ddd329  
Дата: 15.01.11 14:47
Оценка:
Спасибо большое, все получилось!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.