MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 08:50
Оценка:
Не могу понять что означает предупреждение MIDL warning MIDL2284?
Код интерфейса:

    [
        object,
        uuid(B9F67462-D42C-46d1-A560-3FE195BC5AD3),
    
        helpstring("IFFFF Interface"),
        pointer_default(unique)
    ]
    interface IFFFF : IDispatch
    {
        [helpstring("method GetStream")]
         HRESULT GetStream([out] IStream* spStm);
    };
Re: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 29.05.02 09:03
Оценка: 2 (1)
Здравствуйте Valery, Вы писали:

Параметр spStm выходной (out) поэтому его надо передавать через указатель, т.е. надо
[out]IStream** ppStm

Кстати, неплохо было бы в атрибуты интерфейса приписать "dual", а то он от IDispatch наследуется, а без dual толку в этом нет. Тогда для дуального интерфейса придется вместо IStream передавать IUnknown а внтури метода уже брать IStream с помощью QueryInterface
Re[2]: MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 11:18
Оценка:
Здравствуйте Ivan, Вы писали:

I>Параметр spStm выходной (out) поэтому его надо передавать через указатель, т.е. надо

I>[out]IStream** ppStm
Благодарю за пояснение.

I>Кстати, неплохо было бы в атрибуты интерфейса приписать "dual", а то он от IDispatch наследуется, а без dual толку в этом нет. Тогда для дуального интерфейса придется вместо IStream передавать IUnknown а внтури метода уже брать IStream с помощью QueryInterface

IDispatch — для Connection points, а вместо "dual" я хочу поставить oleautomation, чтобы проверить можно ли взаимодействовать с exe сервером без proxy/stub. Кстати нужно-ли в описание интерфейсов точек взаимодействия также вставлять oleautomation?
Re[3]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 29.05.02 11:31
Оценка:
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:



V>IDispatch — для Connection points, а вместо "dual" я хочу поставить oleautomation, чтобы проверить можно ли взаимодействовать с exe сервером без proxy/stub. Кстати нужно-ли в описание интерфейсов точек взаимодействия также вставлять oleautomation?


атрибут Oleautomation позволит использовать typelib маршалинг, т.е. не надо будет proxy/sub компилировать, но зато придется использовать очень ограниченный набор automation-совместимых типов (VARIANT, long, VARIANT_BOOL, BSTR и т.д.), т.е. IStream не покатит для oleautomation интерфейса

Если под точками взаимодействия ты понимаешь IConnectionPointXXX, то их в idl вообще не надо описывать. Описывается только событийный интерфейс.

Событийный интерфейс от IDispatch наследовать не надо. Его надо сделать либо чисто диспинтерфейсом либо унаследовать от IUnknown (при этом можно использовать атриибут oleautomation).
Re[4]: MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 13:18
Оценка:
Здравствуйте Ivan, Вы писали:

I>атрибут Oleautomation позволит использовать typelib маршалинг, т.е. не надо будет proxy/sub компилировать, но зато придется использовать очень ограниченный набор automation-совместимых типов (VARIANT, long, VARIANT_BOOL, BSTR и т.д.), т.е. IStream не покатит для oleautomation интерфейса

O'Key, а если использовать овце-быка типа:
IStreamDsp : virtual public IStream, IDispatch
{
}

далее определить:
[
object,
uuid(B9F67462-D42C-46d1-A560-3FE195BC5AD3),
oleautomation,
helpstring("IFFF Interface"),
pointer_default(unique)
]
interface IFFF : IDispatch
{
     [helpstring("method AAA")]
     HRESULT AAA([out] IStreamDsp** spDStm);
};

В самом методе:
IStream* spStmlocal;
IStreamDsp* spDStmlocal;
...
spDStmlocal = (IStreamDsp*)spStmlocal;
spDStm = &spDStmlocal;
return S_OK;

В клиенте:
IStream* spStmlocal = (IStream*)*spDStm;


и ещё:
Если у кокласса реализовано несколько интерфейсов и
каждый из них имеет точки соединения(IConnectionPoint's),
то должен-ли коклас наследовать для каждого такого интерфейса
public IDispatchImpl<IXXX, &IID_IXXX, &LIBID_CoClassLib>

или достаточно такого наследования от одного какого-либо интерфейса,
например default.
Re[5]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 29.05.02 14:03
Оценка: 2 (1)
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:


V>O'Key, а если использовать овце-быка типа:

V>
V>IStreamDsp : virtual public IStream, IDispatch
Я советую передавать IUnknown* (он ole-automation), а внутри метода вызывать QueryInterface(IID_IStream)



V>и ещё:
V>Если у кокласса реализовано несколько интерфейсов и
V>каждый из них имеет точки соединения(IConnectionPoint's),
V>то должен-ли коклас наследовать для каждого такого интерфейса
V>[ccode]
V>public IDispatchImpl<IXXX, &IID_IXXX, &LIBID_CoClassLib>
V>

V>или достаточно такого наследования от одного какого-либо интерфейса,
V>например default.

Вообще реализация IDispatch всегда одна.Поэтому если все событийные интерфейсы disp-интерфейсы, то можно поддерживать только один из них.

Лучше использовать событийные интерфейсы унаследованные от IUnknown — с ними гораздо проще работать и клиент может поддерживать сразу несколько событийных интерфейсов
Re[6]: MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 14:11
Оценка:
Здравствуйте Ivan, Вы писали:


I>Лучше использовать событийные интерфейсы унаследованные от IUnknown — с ними гораздо проще работать и клиент может поддерживать сразу несколько событийных интерфейсов

А если потребуется познее связывание?
Re[7]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 29.05.02 14:22
Оценка:
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:



I>>Лучше использовать событийные интерфейсы унаследованные от IUnknown — с ними гораздо проще работать и клиент может поддерживать сразу несколько событийных интерфейсов

V>А если потребуется познее связывание?

Для событий позднее связывание практически не используется, поэтому если интерфейс для событий (ConnectPoint's) — его можно смело наследовать от IUnknown
Re[8]: MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 14:34
Оценка:
Здравствуйте Ivan, Вы писали:

I>Для событий позднее связывание практически не используется, поэтому если интерфейс для событий (ConnectPoint's) — его можно смело наследовать от IUnknown

(Вообще-то для скриптов могут быть такие задачи, например распределение работы и т.п.)
В случае наследования от IUnknown коклас должен наследоваться
только от IConnectionPointContainerImpl<CHttpDownload>?
Re[5]: MIDL: warning MIDL2284?
От: Vi2 Удмуртия http://www.adem.ru
Дата: 29.05.02 15:17
Оценка: 6 (2)
Здравствуйте Valery, Вы писали:

Я позволю себе вмешаться в вашу дискуссию. Куда-то она скатывается непонятно куда.

V>O'Key, а если использовать овце-быка типа:

V>IStreamDsp : virtual public IStream, IDispatch
V>{
V>}

V>далее определить:
V>[
V>]
V>interface IFFF : IDispatch
V>{
V>     [helpstring("method AAA")] HRESULT AAA([out] IStreamDsp** spDStm);
V>};


Определение IStreamDsp вверху — это не есть определение СОМ интерфейса — он не может наследоваться от нескольких интерфейсов. СОМ интерфейс может наследовать ТОЛЬКО один СОМ интерфейс. Т.е. в твоём случае, либо IStream, либо IDispatch. И смешивать их нельзя. Это грубейшая ошибка.

V>и ещё:

V>Если у кокласса реализовано несколько интерфейсов и
V>каждый из них имеет точки соединения(IConnectionPoint's),

Тут смешение всего и вся.
Только кокласс имеет точки соединения (CP), а не его интерфейсы.

Чтобы реализовать CP, кокласс должен реализовать интерфейс IConnectionPointContainer и на каждую CP — интерфейс IConnectionPoint, умеющий работать с интерфейсом соединения.

V>то должен-ли коклас наследовать для каждого такого интерфейса

V>
V>public IDispatchImpl<IXXX, &IID_IXXX, &LIBID_CoClassLib>
V>

V>или достаточно такого наследования от одного какого-либо интерфейса,
V>например default.

Поэтому твой класс должен наследовать
    public IConnectionPointContainerImpl<CXXX>,
    public IConnectionPointImpl<CXXX, &IID_IXXXEvents1>,
    public IConnectionPointImpl<CXXX, &IID_IXXXEvents2>,
...
    public IConnectionPointImpl<CXXX, &IID_IXXXEventsN>,

независимо от того, является ли IXXXEventsI наследником IUnknown (custom interface) или IDispatch (dispinterface). Главное, чтобы они отличались друг от друга, IXXXEventsI от IXXXEventsJ по UUID-у.


Вообще, о каких интерфейсах ты говоришь? IXXX или IXXXEvents, имеющем атрибут [source] в описании кокласса в IDL?
А то развели тут — событийный интерфейс, а говорите как об обычном интерфейсе, позднем связывании и т.п.

coclass CXXX
{
    [default] interface IXXX;
    [default, source] interface IXXXEvents;
};
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[9]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 29.05.02 15:18
Оценка:
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:


V>В случае наследования от IUnknown коклас должен наследоваться

V>только от IConnectionPointContainerImpl<CHttpDownload>?

От IConnectionPointContainerImpl<CHttpDownload> наследуется тот, кто будет генерировать события
От событийного интерфейса наследуется (и реализует его) тот, кто собирается получать события
Re[6]: MIDL: warning MIDL2284?
От: Valery  
Дата: 29.05.02 19:28
Оценка:
Здравствуйте Vi2, Вы писали:
...
Спасибо за конструктивную критику и дисциплинирующий тон.

Хочу заметить, что форум на то и существует, чтобы обсуждать вопросы в которых
можно допустить грубые ошибки и если бы я заранее знал ответы на задаваемые вопросы,
то зачем бы я их задавал?. Кроме этого я считаю, что даже зная ответ, во многих случаях
следует интересоваться мнением других людей — это общепринятый путь повышения своих
знаний.

Теперь по существу.
Естественно, моя попытка
IStreamDsp : IStream, IDispatch
{
}

(как я теперь понял) не верна, но не потому что несуществует наследования интерфейсов,
а потому, что такое наследование приводит к наследованию виртуальных методов, а не их реализаций.
Кроме этого мои попытки, сделать приведение об'ектов несостоятельны, т.к. кроме приведения об'ектов в COM нужно "приводить" и таблицы виртуальных функций, а это уже дело QueryInterface.
Поэтому Ivan и ответил что следует вместо IStream передавать IUnknown.
Единственным недостатком при такой реализации метода ,по моему мнению, является нарушение семантики определения метода.

Да я имел ввиду CP (c атрибутом [b]source[/b]]). Меня давно мучал этот вопрос. Я понимал, что CP относятся к кокласу, а не интерфейсу, но во всех книгах описывающих CP рисуют IConnectionPointContainer, как относящийся к кокласу, а IConnectionPoint к интерфейсам. Теперь я убедился, что эти рисунки грешат истиной.
    public IConnectionPointContainerImpl<CXXX>,
    public IConnectionPointImpl<CXXX, &DIID_IXXXEvents1>,
    public IConnectionPointImpl<CXXX, &DIID_IXXXEvents2>,
...
    public IConnectionPointImpl<CXXX, &DIID_IXXXEventsN>,

Из приведенного кода видно, что СЗ принадлежат кокласу (CXXX) и определяютя DIID_IXXXEventsN.
В ATL всеже используется CProxy_IXXXEventsN(CXXX), который в дополнение к методам
IConnectionPointImpl реализует метод Fire_YYY использующий позднее связывание
(pDispatch->Invoke()), в Вашем случае аналогичный метод реализуется как вспомогательный метод кокласа (в принципе различие небольшое).

Теперь о typelib маршалинге.
1. В случае обычных (без атрибута [b]source[/b]])) интерфейсов Ivan мне правильно ответил, что следует
вместо IStream передавать IUnknown. Свое отношение к этому я уже высказал.
2. В случае CP (c атрибутом [b]source[/b]]) Ivan ответил, а MIDL подтвердил, что атрибут oleautomation можно использовать только если _IXXXEventsN наследуется от IUnknown.
В случае dispinterface typelib маршалинг не поддерживается.
Остается открытым вопрос, почему ATL пожертвовала typelib маршалингом в пользу поддержки позднего связывания (возможно потому что COM об'екты созданные скриптовыми языками поддерживают только позднее связывание?).

И последнее — изначально мы затеяли данную дискуcсию чтобы сравнить typelib и proxy/stub маршалинг.
Как всегда получаются вилы — либо простота, либо ясность.
Пока все.
Comments?
Re[6]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 30.05.02 05:48
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>Здравствуйте Valery, Вы писали:



Vi2>Вообще, о каких интерфейсах ты говоришь? IXXX или IXXXEvents, имеющем атрибут [source] в описании кокласса в IDL?

Vi2>А то развели тут — событийный интерфейс, а говорите как об обычном интерфейсе, позднем связывании и т.п.

Вообще-то термин "событийный интерфейс" является вроде бы общепринятым и обозначает интерфейс с атрибутом [source] в idl. При этом никто не запрещает его сделать disp-интерфейсом и использовать позднее связывание для генерирования/получения событий. Но этот прием не является широко распротсраненным (VB не поддерживает позднее связываине для событий — ему tlb с описанием подавай).
Re[7]: MIDL: warning MIDL2284?
От: Ivan Россия www.rsdn.ru
Дата: 30.05.02 05:50
Оценка:
Здравствуйте Valery, Вы писали:

V> В случае dispinterface typelib маршалинг не поддерживается.

V>Comments?

Для дисп-интерфейсов oleautomation маршалинг поддерживается, просто не надо явно атрибут oleautomation указывать (то же самое и для дуальных интерфейсов).
Но я советовал использовать события IUnknown, так как с ними гораздо проще работать.
Re[7]: CP-объектики и маршалинг
От: Vi2 Удмуртия http://www.adem.ru
Дата: 30.05.02 05:54
Оценка:
Здравствуйте Valery, Вы писали:

V>Естественно, моя попытка

V>IStreamDsp : IStream, IDispatch
V>{
V>}

V>(как я теперь понял) не верна, но не потому что несуществует наследования интерфейсов,
V>а потому, что такое наследование приводит к наследованию виртуальных методов, а не их реализаций.
V>Кроме этого мои попытки, сделать приведение об'ектов несостоятельны, т.к. кроме приведения об'ектов в COM нужно "приводить" и таблицы виртуальных функций, а это уже дело QueryInterface.
V>Поэтому Ivan и ответил что следует вместо IStream передавать IUnknown.

IUnknown* следует передавать вместо IStream*, если необходимо, чтобы интерфейс был oleautomation, потому что IStream не является oleautomation-совместимым. Если нужды такой нет, то можно передавать как IUnknown*, так и IStream*.
QueryInterface используется для получения интерфейса, отличного от переданного. Т.е. если нужно получить другой интерфейс объекта, вызываешь этот метод.

V>Единственным недостатком при такой реализации метода ,по моему мнению, является нарушение семантики определения метода.


Передача параметров должна быть продумана. Ты можешь передавать IStream, но следует учитывать, что не все клиенты могут воспользоваться этим интерфейсом. VC-клиент без проблем воспользуется, а вот у VB-клиента могут быть проблемы. Например, он если и сможет получить такой интерфейс, то единственное, что он сможет дальше, — это передать входным параметром в другой метод. Сам клиент использовать интерфейс не сможет, т.е. не сможет вызывать методы этого интерфейса.

V>Да я имел ввиду CP (c атрибутом [b]source[/b]]). Меня давно мучал этот вопрос. Я понимал, что CP относятся к кокласу, а не интерфейсу, но во всех книгах описывающих CP рисуют IConnectionPointContainer, как относящийся к кокласу, а IConnectionPoint к интерфейсам. Теперь я убедился, что эти рисунки грешат истиной.


Ну, не совсем и грешат. CP-объектики обладают всего двумя интерфейсами: IConnectionPoint и IUnknown. Они отвечают за вызовы методов интерфейса событий, они умеют это делать, потому как знают все об этом интерфейсе. Поэтому они относятся к интефейсам, но ещё больше они привязаны к коклассу, как к объекту, который генерит события. Именно объект сервера инициирует вызов метода интерфейса событий через посредство CP-объектика. Без него вообще говорить о событиях нечего.

А раз CP-объектик знают все об интерфейсе, то вопрос о "позднем" или "раннем" связывании не стоит. Метод может быть вызван или напрямую через виртуальную таблицу или через IDispatch::Invoke. Этот способ уже зашит в CP-объект. Поэтому Ivan и говорил или о наследовании от IUnknown или о чистом IDispatch (т.е. dispinterface). Преимущество dual-интерфейсов в работе или через vtable или через Invoke здесь не проявляется, так как вызовы уже определены.

V>Теперь о typelib маршалинге.

V>1. В случае обычных (без атрибута [b]source[/b]])) интерфейсов Ivan мне правильно ответил, что следует
V> вместо IStream передавать IUnknown. Свое отношение к этому я уже высказал.
V>2. В случае CP (c атрибутом [b]source[/b]]) Ivan ответил, а MIDL подтвердил, что атрибут oleautomation можно использовать только если _IXXXEventsN наследуется от IUnknown.
V> В случае dispinterface typelib маршалинг не поддерживается.

V>Остается открытым вопрос, почему ATL пожертвовала typelib маршалингом в пользу поддержки позднего связывания (возможно потому что COM об'екты созданные скриптовыми языками поддерживают только позднее связывание?).


V>И последнее — изначально мы затеяли данную дискуcсию чтобы сравнить typelib и proxy/stub маршалинг.

V>Как всегда получаются вилы — либо простота, либо ясность.

А вопрос о маршалинге и прост и сложен одновременно. Любой интерфейс должен маршалироваться. Для любого описания интерфейса proxy/stub прекрасно справится со своей задачей. Даже для oleautomation ты можешь использовать свои proxy/stub. Просто в случае oleautomation ты можешь этого не делать — стандартная библиотека СОМ сделает это за тебя. Но за это приходится платить использованием ограниченного набора данных.

Поэтому typelib маршалинг используется для интерфейсов с oleautomation, в частности и для dispinterface (он по определению oleautomation).
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[8]: CP-объектики и маршалинг
От: Valery  
Дата: 30.05.02 06:49
Оценка:
Здравствуйте Vi2, Вы писали:


Vi2>Ну, не совсем и грешат. CP-объектики обладают всего двумя интерфейсами: IConnectionPoint и IUnknown. Они отвечают за вызовы методов интерфейса событий, они умеют это делать, потому как знают все об этом интерфейсе. Поэтому они относятся к интефейсам, но ещё больше они привязаны к коклассу, как к объекту, который генерит события.

Не согласен. CP об'екты (через Advise) получают указатели на sink об'екты (интерфейсы) клиента
и никакого отношения к интерфейсам кокласа не имеют (только уж очень-очень косвенный — sink об'ект клиента может вызвать,а может и не вызвать метод какогото интерфейса. В принципе это его личное дело, а не CP об'екта).
Более того, ничего не мешает одному CP-об'екту "поджечь" все имеющиеся соединения.
Re[6]: IDispatch против IUnknown
От: Valery  
Дата: 30.05.02 07:39
Оценка:
Здравствуйте Ivan, Вы писали:

I>Лучше использовать событийные интерфейсы унаследованные от IUnknown - с ними гораздо проще работать и клиент может поддерживать сразу несколько событийных интерфейсов

Можно ли поподробней пояснить это утверждение?
По поводу количества событийных интерфейсов поддерживаемых клиентом — сколько разных об'ектов sink клиент создаст, столько и будет поддерживать событийных интерфейсов (вроде с первого взгляда от IUnknown это не зависит).
Также кажется, что раз уж IDispatch наследуется от IUnknown то с интерфейсами наследуемыми от IDispatch можно работать как с интерфейсами наследуемыми от IUnknown (в частности переписать под IUnknown методы Fire_). Правда сами интерфейсы станут более "тяжеловесными", что может сказаться на трафике при удаленной передаче.
Какие еще "за" за IUnknown?
Re[7]: IDispatch против IUnknown
От: Ivan Россия www.rsdn.ru
Дата: 30.05.02 07:45
Оценка: 4 (1)
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:

V>Какие еще "за" за IUnknown?

Дело в том, что в ATL по-моему нет поддержки нескольких IDispatch интерфейсов одновременно, то есть через IDispatch->Invoke снаружи будет доступен только какой-нибудь один из них, а остальные только через vtbl.
Поэтому если объявить несколько source-интерфейсов (я их нгазываю событийными), то либо придется на клиенте свою реализацию IDispatchImplSUPER, которая будет поддерживать несколько disp-интерфейсов одновременно, либо использовать vtbl, а в этом случае лучше использовать IUnknown source-интерфейсы

В принципе как вариант можно у клиента завести несколько COM-объектов, по одному на каждый source-интерфейс и тогда использовать IDispatch
Re[8]: IDispatch против IUnknown
От: Valery  
Дата: 30.05.02 09:17
Оценка:
Здравствуйте Ivan, Вы писали:

I>Дело в том, что в ATL по-моему нет поддержки нескольких IDispatch интерфейсов одновременно, то есть через IDispatch->Invoke снаружи будет доступен только какой-нибудь один из них, а остальные только через vtbl.

I>Поэтому если объявить несколько source-интерфейсов (я их нгазываю событийными), то либо придется на клиенте свою реализацию IDispatchImplSUPER, которая будет поддерживать несколько disp-интерфейсов одновременно, либо использовать vtbl, а в этом случае лучше использовать IUnknown source-интерфейсы

I>В принципе как вариант можно у клиента завести несколько COM-объектов, по одному на каждый source-интерфейс и тогда использовать IDispatch

Я боюсь ошибиться, но мне кажется есть:
http://www.microsoft.com/msj/defaultframe.asp?page=/msj/1299/VisualProg/VisualProg1299.htm
Это то или нет?
К сожалению серьезно пописать и поразбираться я смогу только в субботу-воскресенье.
Re[9]: IDispatch против IUnknown
От: Ivan Россия www.rsdn.ru
Дата: 30.05.02 09:30
Оценка: 2 (1)
Здравствуйте Valery, Вы писали:

V>Здравствуйте Ivan, Вы писали:


V>Это то или нет?

Это как раз "оно". С помощью IDispatchEventImpl можно ловить события на disp-интерфейсе ( но по-моему только на одном).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.