Это не работает (hr содержит код ошибки Incorrect argument). Насколько я понимаю, аргументы SAFEARRAY всегда передаются, как указатели на указатели, независимо от того, in или out?
Кто-нибудь может подсказать, как правильно передавать SAFEARRAY через Invoke?
2. В IDispatch нет понятия [out]. Есть [out, retval] и тогда результат надо получать и передовать через varResult (в Вашем случае). И есть ByRef. Лучше даже описывать параметр не как [out], а как [in, out].
Точно не помню, pparray может называться по другому.
3. В примере есть одно излишиство:
CComVariant* pvars = new CComVariant[3];
намного проще так:
CComVariant vars[3];
LT>Это не работает (hr содержит код ошибки Incorrect argument). Насколько я понимаю, аргументы SAFEARRAY всегда передаются, как указатели на указатели, независимо от того, in или out?
Нет, это не так. out всегда прибавляет лишную звездочку — это соглашение COM-а.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Проблемы с передачей SAFEARRAY через Dispatch
Спасибо всем за ответы, сделал через VARIANT, и все заработало.
VD>[in]-параметрам не надо добавлять *.
Это уже своего рода "шаманство", перед этим был вариант без указателей...
VD>2. В IDispatch нет понятия [out]. Есть [out, retval] и тогда результат надо получать и передовать через varResult (в Вашем случае). И есть ByRef. Лучше даже описывать параметр не как [out], а как [in, out].
Имхо, это не совсем так. Я достаточно часто использую просто [out], и это замечательно работает. Кстати, в моем случае с VARIANTами используется именно [out]. И это работает.
VD>В коде вызова для [out]-параметра надо указывать: VD>vars[0].vt = VT_BYREF | VT_ARRAY | VT_UI1; VD>vars[0].pparray = &psaZBuffer;
Делал и так, не помогало...
VD>3. В примере есть одно излишиство: VD>CComVariant* pvars = new CComVariant[3]; VD>намного проще так: VD>CComVariant vars[3];
Согласен, но это код, сгенерированный wizard-ом, я вносил только необходимые исправления.
Re[3]: Проблемы с передачей SAFEARRAY через Dispatch
Здравствуйте LoneTiger, вы писали:
VD>>2. В IDispatch нет понятия [out]. Есть [out, retval] и тогда результат надо получать и передовать через varResult (в Вашем случае). И есть ByRef. Лучше даже описывать параметр не как [out], а как [in, out].
LT>Имхо, это не совсем так. Я достаточно часто использую просто [out], и это замечательно работает. Кстати, в моем случае с VARIANTами используется именно [out]. И это работает.
Не, ну если надо не проблемы решать, а по дискутировать, то конечно... Вот только мне что-то спорить не охота. :( Эти грабли не у Вас первого не у Вас последнего. По-моему, в MS-ной русскоязычной конфе по VC я как-то уже правил подобный код. Повторю еще раз, но это последний.
В IDISPATCH нет понятия чистого [out]-а! Этот интерфейс создавался для VB старых версий, а в нем вообще нет понятия out-параметров. Я ясно излагаю? В dual-интерфейсе Вы можете описать патаметр как чистый out, но при вызове через его IDispatch-часть Вам все равно прийдется передавать параметы ByRef. Ну, вот так криво написан этот IDispatch! У вас могут быть и другие проблемы с out-параметрами при использовании в VB. Вот я Вам и советую описать параметр как [in, out]. Содя по отвту на последнее замечание Вы не просто описываете онтерфейс, а интерфейс событийный. Верно? Ну, вроде точно верно. А если так, то вы делаете еще более грубую ошибку описывая событийный интерфейс как dual! Это еще одни грабли на которые лучше не наступать. Просто запомните: Если Вы не хотите иметь проблем, не реализуйте событийный интерйейс как dual!
Реализуйте его или как чистый dispinterface или как чистый custom-интерфенйс (производный тлько от IUnknown). Перый, вариант нужен для совметимости с VB версии ниже 6-й и скриптовыми языками. Второй, если используете преимущественно C++ и потенциально VB6 (это так же значительно быстрее). Ну, а елси охота походить по граблям... ;o)
VD>>В коде вызова для [out]-параметра надо указывать: VD>>vars[0].vt = VT_BYREF | VT_ARRAY | VT_UI1; VD>>vars[0].pparray = &psaZBuffer;
LT>Делал и так, не помогало...
Значит ощибка гдето еще или пробавали не совсем так. Кадайте код погляжу. audit@optim.ru. Кстати, а на чем реализуются события? VB6?
VD>>3. В примере есть одно излишиство: VD>>CComVariant* pvars = new CComVariant[3]; VD>>намного проще так: VD>>CComVariant vars[3];
LT>Согласен, но это код, сгенерированный wizard-ом, я вносил только необходимые исправления.
Да, видимо люди писавшие этот код или много выпили или писали его поздно ночью. :)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Проблемы с передачей SAFEARRAY через Dispatch
Здравствуйте VladD2, вы писали:
VD>Не, ну если надо не проблемы решать, а по дискутировать, то конечно... Вот только мне что-то спорить не охота. :( Эти грабли не у Вас первого не у Вас последнего. По-моему, в MS-ной русскоязычной конфе по VC я как-то уже правил подобный код. Повторю еще раз, но это последний.
Ну не надо так нервничать :) Во-первых, это было имхо (я не претендую на истину в последней инстанции), во-вторых, мне интересно разобраться в этой ситуации. Поэтому любая информация по этому вопросу имеет для меня ценность. Дело в том, что я не использую VB, весь проект на VC. Поэтому я и заинтересовался — будет ли чистый [out] в IDispatch нормально работать в VC.
VD>В IDISPATCH нет понятия чистого [out]-а! Этот интерфейс создавался для VB старых версий, а в нем вообще нет понятия out-параметров. Я ясно излагаю? В dual-интерфейсе Вы можете описать патаметр как чистый out, но при вызове через его IDispatch-часть Вам все равно прийдется передавать параметы ByRef. Ну, вот так криво написан этот IDispatch! У вас могут быть и другие проблемы с out-параметрами при использовании в VB. Вот я Вам и советую описать параметр как [in, out]. Содя по отвту на последнее замечание Вы не просто описываете онтерфейс, а интерфейс событийный. Верно? Ну, вроде точно верно. А если так, то вы делаете еще более грубую ошибку описывая событийный интерфейс как dual! Это еще одни грабли на которые лучше не наступать. Просто запомните: Если Вы не хотите иметь проблем, не реализуйте событийный интерйейс как dual!
Угу, все понятно. Проблема в том, что реализация поддержки событий была сгенерирована тем же wizard-ом (тудыть его в качель!), поэтому грабли это не совсем мои :) Я вот одного не понимаю: зачем было делать такой кривой wizard? Если все на самом деле так, как Вы говорите, почему Microsoft до сих пор не пропатчила это дело? У меня стоит SP5, wizard там такой же кривой. В чем тут дело?
VD>Реализуйте его или как чистый dispinterface или как чистый custom-интерфенйс (производный тлько от IUnknown). Перый, вариант нужен для совметимости с VB версии ниже 6-й и скриптовыми языками. Второй, если используете преимущественно C++ и потенциально VB6 (это так же значительно быстрее). Ну, а елси охота походить по граблям... ;o)
Тогда я не совсем понимаю, как будет работать механизм IConnectionPoint. Ведь там все завязано именно на IDispatch, не так ли? Если мой Sink интерфейс будет наследовать только IUnknown, каким макаром будут выполняться вызовы его методов? Объясните, если не сложно.
VD>Значит ощибка гдето еще или пробавали не совсем так. Кадайте код погляжу. audit@optim.ru. Кстати, а на чем реализуются события? VB6?
Спасибо, но у меня уже все заработало. И клиент, и сервер написаны на VC6.
VD>Да, видимо люди писавшие этот код или много выпили или писали его поздно ночью. :)
Эх... мелкософт, одно слово :(
Re[5]: Проблемы с передачей SAFEARRAY через Dispatch
Здравствуйте LoneTiger, вы писали:
LT>Здравствуйте VladD2, вы писали:
LT>Ну не надо так нервничать :) Во-первых, это было имхо (я не претендую на истину в последней инстанции), во-вторых, мне интересно разобраться в этой ситуации. Поэтому любая информация по этому вопросу имеет для меня ценность. Дело в том, что я не использую VB, весь проект на VC. Поэтому я и заинтересовался — будет ли чистый [out] в IDispatch нормально работать в VC.
Мужик (ничего что на ты?) ты уже десятый кто на мойе памяти по этим граблям ходит! И половина не обяснения требует, а спорить лезит. Вот и злюсь. Ну, ладно... проехали. :)
LT>Угу, все понятно. Проблема в том, что реализация поддержки событий была сгенерирована тем же wizard-ом (тудыть его в качель!), поэтому грабли это не совсем мои :) Я вот одного не понимаю: зачем было делать такой кривой wizard? Если все на самом деле так, как Вы говорите, почему Microsoft до сих пор не пропатчила это дело? У меня стоит SP5, wizard там такой же кривой. В чем тут дело?
Да! Визард глючный. Вернее он (они) не контролирует, что а) нельзя делать дуальный интерфейс событийным, в) в дисп-интерфейсе нельзя объявлять парамтр как чистый out. Игнорируя это он просто генерирует глючный код (хотя может он бдет глючить и на [in, out]-параметы). :(
LT>Тогда я не совсем понимаю, как будет работать механизм IConnectionPoint. Ведь там все завязано именно на IDispatch, не так ли? Если мой Sink интерфейс будет наследовать только IUnknown, каким макаром будут выполняться вызовы его методов? Объясните, если не сложно.
Замечательно будет работать. IDispatch — там совсем не нужен. VB (а уж на сях сам бог велел) прекрасно работает с кастом-интерфейсами. Это кстати раз в десять быстрей. Да, и на C++ проще с нормальными интерфейсами. Если мне не изменяет мой склероз, визард даже с ними работать умеет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Проблемы с передачей SAFEARRAY через Dispatch
Здравствуйте VladD2, вы писали:
VD>Мужик (ничего что на ты?) ты уже десятый кто на мойе памяти по этим граблям ходит! И половина не обяснения требует, а спорить лезит. Вот и злюсь. Ну, ладно... проехали. :)
ОК, на ты так на ты :)))
VD>Да! Визард глючный. Вернее он (они) не контролирует, что а) нельзя делать дуальный интерфейс событийным, в) в дисп-интерфейсе нельзя объявлять парамтр как чистый out. Игнорируя это он просто генерирует глючный код (хотя может он бдет глючить и на [in, out]-параметы). :(
Тогда вопрос: а где бы про все эти хитрости почитать? Я вот, например, не сталкивался нигде с упоминанием того факта, что в IDispatch нельзя использовать out. Откуда эта информация?
VD>Замечательно будет работать. IDispatch — там совсем не нужен. VB (а уж на сях сам бог велел) прекрасно работает с кастом-интерфейсами. Это кстати раз в десять быстрей. Да, и на C++ проще с нормальными интерфейсами. Если мне не изменяет мой склероз, визард даже с ними работать умеет.
Да я просил объяснить, КАК это будет работать. Как это работает с IDispatch, я понимаю. Как это будет работать в случае обычного недуального интерфейса, я, честно говоря, не представляю. Можно хотя бы ссылочку какую-нибудь?
Re[7]: Проблемы с передачей SAFEARRAY через Dispatch
Здравствуйте LoneTiger, вы писали:
LT>Тогда вопрос: а где бы про все эти хитрости почитать? Я вот, например, не сталкивался нигде с упоминанием того факта, что в IDispatch нельзя использовать out. Откуда эта информация?
Ну, кое что есть у нас на сайте www.optim.ru/sc , а можно и здесь. Основной материал в MSDN (но мало и найти тяжело), Iinside OLE помогает... но главное это хорошенько потрахаться. Обычно достаточно года 3-4. :( Особо помогает трах с VB (5 — 6).
LT>Да я просил объяснить, КАК это будет работать. Как это работает с IDispatch, я понимаю. Как это будет работать в случае обычного недуального интерфейса, я, честно говоря, не представляю. Можно хотя бы ссылочку какую-нибудь?
template <class T>
class CProxy_IascColumnsEvents : public IConnectionPointImpl<T, &IID__IascColumnsEvents, CComDynamicUnkArray>
{
//Warning this class may be recreated by the wizard.
public:
HRESULT Fire_AfterNameChanged(LONG ColumnNumber, BSTR NewName)
{
T* pT = static_cast<T*>(this);
if(pT->EventsFreezed())
return S_FALSE;
HRESULT ret = S_FALSE;
int nConnections = m_vec.GetSize();
for (int nConnectionIndex = 0; nConnectionIndex < nConnections && SUCCEEDED(ret); nConnectionIndex++){ pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock();
_IascColumnsEvents* p_IascColumnsEvents = reinterpret_cast<_IascColumnsEvents*>(sp.p);
if (p_IascColumnsEvents != NULL)
ret = p_IascColumnsEvents->AfterNameChanged(ColumnNumber, NewName);
}
ASC_RETURN_FAILED(ret);
Клиент реализует интерфейс _IascColumnsEvents и подключается через Advise. Собственно все! И никакой разницы с диспачным вариантом. А вот с дуал-интерфейсом это прокатит только если и клиент и сервер написан на сях. VB реализует только диспачную часть и при вызове нормальной произойдет AV. Если же вызывать только диспачную часть, то нахреда делать сам интерфейс дуальным.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.