Отчёт о дуальных событийных интерфейсах
От: Tom Россия http://www.RSDN.ru
Дата: 24.10.02 12:31
Оценка: 64 (3)
В одном топике немного ниже обсуждалась эта проблемма. Я решил проверить действительно ли сабж. невозможен. Написал простенький сервер на ATL с использованием визарда. Сделал сервер с 1 функцией DoVoctory которая генерит одно событие OnVictory, на которое сожусь из VB стандартным способом. Результат: Если событийный интерфейс обьявлен с атрибутом dual, то действительно VB ругается, но если с oleautomation, то всё ок и событие генериться... Так что всё ок. Весь код приведён ниже.

IDL файл.
import "oaidl.idl";
import "ocidl.idl";

    //-----------------------------------------------------------------
    [
        object,
        uuid(0481D2ED-E723-11D6-872F-0000214538D0),
        dual,
        helpstring("IEvObj Interface"),
        pointer_default(unique)
    ]
    interface IEvObj : IDispatch
    {
        [id(1), helpstring("method DoVictory")] HRESULT DoVictory();
    };

    //-----------------------------------------------------------------
    [
        oleautomation,
        uuid(0481D2EF-E723-11D6-872F-0000214538D0),
        helpstring("IEventEvObj Interface")
    ]
    interface IEventEvObj : IDispatch
    {
        [helpstring("method OnVictory")] HRESULT OnVictory();
    };

    //-----------------------------------------------------------------
[
    uuid(0481D2E1-E723-11D6-872F-0000214538D0),
    version(1.0),
    helpstring("lernEv 1.0 Type Library")
]
library LERNEVLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");

    [
        uuid(0481D2EE-E723-11D6-872F-0000214538D0),
        helpstring("EvObj Class")
    ]
    coclass EvObj
    {
        [default] interface IEvObj;
        [default, source] interface IEventEvObj;
    };
};


H — файл сервера.
#ifndef __EVOBJ_H_
#define __EVOBJ_H_

#include "resource.h"       // main symbols

class ATL_NO_VTABLE CEvObj : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CEvObj, &CLSID_EvObj>,
    public IConnectionPointImpl<CEvObj, &IID_IEventEvObj>,
    public IConnectionPointContainerImpl<CEvObj>,
    public IDispatchImpl<IEvObj, &IID_IEvObj, &LIBID_LERNEVLib>
{
public:
    CEvObj()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_EVOBJ)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CEvObj)
    COM_INTERFACE_ENTRY(IEvObj)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CEvObj)
    CONNECTION_POINT_ENTRY(IID_IEventEvObj)
END_CONNECTION_POINT_MAP()


// IEvObj
public:
    STDMETHOD(DoVictory)();
};

#endif //__EVOBJ_H_


CPP файл сервера, содержащий метод DoVictory, который генерит событие
#include "stdafx.h"
#include "LernEv.h"
#include "EvObj.h"

STDMETHODIMP CEvObj::DoVictory()
{
    HRESULT hr = 0;
    IEventEvObj * pE = NULL;
    
    pE = (IEventEvObj *) m_vec.GetAt(0); 
    pE->OnVictory();
    return S_OK;
}


Клиент на VB.

Private WithEvents obj As EvObj
Private Sub Command1_Click()
    Set obj = New EvObj
    obj.DoVictory
End Sub
Private Sub obj_OnVictory()
    MsgBox "Victory"
End Sub


Вроде и всё. Если некоторые мне скажут, что без атрибута dual интерфейс не есть дуальный возражу следующим образом: "Дуальный интерфейс — интерфейс, методы которого можно вызывать и через IDispatch и через VTBL, что и достигнуто в данном примере. Тем более атрибут oleautomation позволит использовать стандартный маршалер.". Открытым остаётся один вопрос: "Почему VB ругнулся на dual". Попытаюсь это выяснить м доложу о результатах...

ЗЫ: Если кому вдруг понадобятся сырцы могу выслать...
Народная мудрось
всем все никому ничего(с).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.