Zdarzenia (events, connection points)

Podobne dokumenty
//////////////////////////////////////////////////////////// // Kalkulator (prosty) - wersja agregowalna import "unknwn.idl";

Agregacja. Wykorzystanie innego komponentu bez użycia agregacji. Simple calculator. Extended calculator

Microsoft Interface Definition Language

Obiekty w plikach wykonywalnych, marshaling

4 bity zarezerwowane dla przyszłych zastosowań 11 bitów określających źródło błędu 16 bitów określających rodzaj błędu.

Droga do DCOM DCOM (1996) Windows clipboard (1987) OLE 1 DDE (1992) OLE 2 (1993) COM (1995) Distributed computing (1980s)

Wywoływanie metod zdalnych

Wywoływanie metod zdalnych

Structured storage, Monikers, Running Object Table

Wyjątki (exceptions)

Remote Method Invocation 17 listopada 2010

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Systemy Rozproszone - Ćwiczenie 6

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Aplikacje internetowe i rozproszone - laboratorium

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Zarządzanie pamięcią

PHP 5 język obiektowy

1. Wybierz File New Application. Pojawi się nowa aplikacja w Delphi.

Technologie COM i ActiveX COM - Component Object Model

Aplikacje RMI

Zad.30. Czy można utworzyć klasę, która implementuje oba interfejsy?

Wzorce Strukturalne. Adapter: opis. Tomasz Borzyszkowski

Remote Method Invocation 17 listopada rozproszonych. Dariusz Wawrzyniak (IIPP) 1

Dawid Gierszewski Adam Hanasko

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Programowanie obiektowe

Podstawy Programowania Obiektowego

Henryk Budzisz. materiały przygotowane w ramach projektu ZPORR nr POKL /08-00

Proxy (pełnomocnik) Cel: Zastosowanie: Dostarczyć zamiennik pewnego obiektu, pozwalający kontrolować dostęp do niego.

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Klasy abstrakcyjne, interfejsy i polimorfizm

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Programowanie 2. Język C++. Wykład 3.

Współbieżność w środowisku Java

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

Interfejs IUnknown. Każdy obiekt COM musi implementować interfejs IUnknown, który zawiera trzy metody:

DYNAMICZNE PRZYDZIELANIE PAMIECI

Aplikacje RMI Lab4

Architektura składnikowa a architektura klient serwer. Programowanie składnikowe. Programowanie składnikowe w modelu COM

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Klasy cd. Struktury Interfejsy Wyjątki

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Konstruktor kopiujacy

Zdalne uruchamianie obiektów COM

Wprowadzenie. Dariusz Wawrzyniak 1

Enterprise JavaBeans (EJB)

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Programowanie składnikowe. Programowanie składnikowe w modelu COM. COM - Component Object Model. wprowadzenie. Programowanie składnikowe

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Zaawansowane programowanie w C++ (PCP)

Szablony funkcji i klas (templates)

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Polimorfizm. dr Jarosław Skaruz

Programowanie współbieżne i rozproszone

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Michał Jankowski. Remoting w.net 2.0

Serwery Statefull i Stateless

Zaawansowane aplikacje internetowe

Wprowadzenie do szablonów szablony funkcji

Szablony klas, zastosowanie szablonów w programach

Programowanie Obiektowe GUI

Java: interfejsy i klasy wewnętrzne

PARADYGMATY PROGRAMOWANIA Wykład 4

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej.

Listy powiązane zorientowane obiektowo

1 Atrybuty i metody klasowe

Wprowadzenie do szablonów szablony funkcji

AXIS2 - tworzenie usługi sieciowej i klienta Axis Data Binding. dr inż. Juliusz Mikoda mgr inż. Anna Wawszczak

Referencje do zmiennych i obiektów

Builder (budowniczy) Cel: Przykład:

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Aplikacje w środowisku Java

Fragmenty są wspierane od Androida 1.6

Plan prezentacji. Budowa aplikacji w technologii Enterprise JavaBeans. Przegląd architektur: CORBA. Cele budowy aplikacji rozproszonych

AKADEMIA GÓRNICZO-HUTNICZA Wydział Elektrotechniki, Automatyki, Elektroniki i Informatyki

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Podstawy programowania w języku C++

Katedra Architektury Systemów Komputerowych Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej

Szablony funkcji i szablony klas

Wykład 4: Klasy i Metody

Transkrypt:

(events, connection points)

Serwer komunikuje się z klientem za pomocą zgłoszenia zdarzenia. Pozwala to na asynchroniczną pracę serwera, który zgłasza zaistnienie określonego stanu za pomocą serii zdarzeń. Odbywa się to poprzez wywołanie metod interfejsu, który implementowany jest przez klienta. Klient w takim przypadku posiada również cechy serwera, gdyż jest w stanie odbierać wywołania komponentu.

Komponent musi mieć wstępnie zdefiniowany zestaw zdarzeń (strukturę interfejsu), przez które będzie się odwoływał do klienta. Dlatego interfejs, który implementowany jest przez klienta, musi być zdefiniowany wraz z interfejsami komponentu i wyróżniony jako odbiorca zdarzeń. W ten sposób komponent stawia wymagania w stosunku do klienta.

[ object, uuid(6764b148-93be-40c1-b2ba-81650c57e33e), oleautomation ] interface ICountdown : IUnknown... ; [ object, uuid(95c0b4ce-a39b-463a-be4b-06137333bd8e), oleautomation ] interface ICountdownEvents :IUnknown HRESULT EverySecondTick( [in] int ElapsedTime ); ; [ uuid(d7eba784-2bf1-11d3-a48b-0000861c844e), version(version), helpstring("timers 3.0 Type Library") ] library CounterLib coclas Counter interface ICountdown; [source] interface ICountdownEvents; ;

IConnectionPointContainer Zanim klient uruchomi proces komponentu, który może zgłosić zdarzenie, musi przekazać mu swój interfejs. Przez przekazaniem interfejsu sprawdza czy posiadany interfejs odpowiada wymaganiom komponentu, a następnie przekazuje mu wskaźnik do swojego interfejsu IUnknown. Klient weryfikuje swój interfejs za pomocą odwołań do interfejsu IConnectionPointContainer. Interfejs ten musi być zaimplementowany przez komponent.

IConnectionPointContainer IUnknown IConnectionPointContainer IConnectionPoint IConnectionPoint IConnectionPoint interface IConnectionPointContainer : IUnknown HRESULT EnumConnectionPoints ( [out] IEnumConnectionPoints ** ppenum ); HRESULT FindConnectionPoint ( [in] REFIID riid, [out] IConnectionPoint ** ppcp ); Komponent

IConnectionPointContainer HRESULT FindConnectionPoint ( [in] REFIID riid, [out] IConnectionPoint ** ppcp ); odpowiada żadnemu z interfejsów wymaganych przez Metoda FindConnectionPoint zwraca klientowi interfejs IConnectionPoint, który odpowiada posiadanemu interfejsowi. Gdy podany GUID nie komponent, zwrócony zostaje błąd E_NOINTERFACE. HRESULT CCountdown::FindConnectionPoint(REFIID riid, IConnectionPoint ** ppcp) if (riid==iid_icountdownevents) return QueryInterface(IID_IConnectionPoint, (void**)ppcp); return E_NOINTERFACE;

IConnectionPointContainer HRESULT EnumerateConnectionPoints ( [out] IEnumConnectionPoints ** ppenum ); Metoda EnumConnectionPoints zwraca obiekt typu IEnumConnectionPoints, który pozwala na dostęp do wszystkich obiektów IConnectionPoint wspieranych przez komponent. Pełna implementacja tej metody jest istotna, gdy komponent wspiera różne rodzaje interfejsów zdarzeń. Może ona zwracać E_NOIMPL.

IConnectionPoint Komponent dla każdego typu interfejsu źródłowego (odbierającego zdarzenia) powinien mieć zaimplementowany obiekt IConnectionPoint. W najprostszym przypadku, gdy jest tylko jeden rodzaj interfejsu źródłowego, komponent może bezpośrednio dziedziczyć IConnectionPoint. Metody tego interfejsu służą klientowi do zgłaszania (rejestracji) wskaźnika swojego IUnknown. interface IConnectionPoint : IUnknown HRESULT GetConnectionInterface( [out] IID * piid ); HRESULT GetConnectionPointContainer( [out] IConnectionPointContainer **ppcpc); HRESULT Advise( [in] IUnknown * punksink, [out] DWORD * pdwcookie ); HRESULT Unadvise( [in] DWORD dwcookie ); HRESULT EnumConnections( [out] IEnumConnections ** ppenum );

IConnectionPoint HRESULT GetConnectionInterface( [out] IID * piid ); Metoda GetConnectionPointInterface() pozwala na identyfikację z jakim interfejsem źródłowym skojarzony jest obiekt IConnectionPoint. Metoda ta jest szczególnie użyteczna podczas wyliczania obiektów IConnectionPoint za pomocą obiektu IEnumConnectionPoints.

IConnectionPoint HRESULT GetConnectionPointContainer( [out] IConnectionPointContainer **ppcpc); Metoda GetConnectionPointContainer() zwraca rodzicielski obiekt IConnectionPointContainer. HRESULT Advise( [in] IUnknown * punksink, [out] DWORD * pdwcookie ); Metoda Advise() pozwala przekazać klientowi wskaźnik swojego interfejsu źródłowego (poprzez IUnknown), do którego przekazywane będą zdarzenia. Metoda ta zwraca identyfikator, który później pozwala rozróżnić klientów, w przypadku gdy więcej niż jeden korzysta z tego samego komponentu.

IConnectionPoint HRESULT Unadvise( [in] DWORD dwcookie ); Metoda Unadvise() informuje komponent, aby nie próbował już wywoływać metod wskazanego klienta. HRESULT EnumConnections([out] IEnumConnections ** ppenum); Metoda EnumConnections() zwraca obiekt IEnumConnections pozwalający na dostęp do wszystkich aktywnych interfejsów zgłoszonych przez klientów metodą Advise().

IConnectionPoint HRESULT Advise(IUnknown * punksink, DWORD * pdwcookie) *pdwcookie = 1; return punksink->queryinterface(iid_icountdownevents, (void**)&g_poutgoing); HRESULT Unadvise(DWORD dwcookie) g_poutgoing->release(); g_poutgoing=null; return S_OK; HRESULT GetConnectionInterface(IID * piid) *piid=iid_icountdownevents; return S_OK; HRESULT GetConnectionPointContainer(IConnectionPointContainer **ppcpc) return QueryInterface(IID_IConnectionPointContainer, (void**)ppcpc);

Klient main () try CCountdownPtr pcountdown(clsid_counter); IConectionPointContainer* pcpcontainer; IConectionPoint* pcp; DWORD dwcookie; pcountdown->queryinterface(iid_iconectionpointcontainer, (void**)&pcpcontainer); hr=pcpcontainer->findconnectionpoint(iid_icountdownevents,&pcp); if (FAILED(hr))...; CCountdownEvents* pcountdownevents=new CCountdownEvents; hr=pcp->advise((iunknown*)pcountdownevents,&dwcookie); if (FAILED(hr))...; pcountdown->startcounter(100);... //do some job hr=pcp->unadvise(dwcookie); pcp->release(); pcpcontainer->release(); pcountdown=null; catch()...

Klient HRESULT CCountdownEvents::EverySecondTick(int ElapsedTime) PlaySound("Tick",NULL,SND_RESOURCE SND_ASYNC); cout << "Time to go: " << ElapsedTime << endl; return S_OK;

ATL wizard -uwagi ATL wizard pozwala na automatyczną generację kodu dla interfejsów IConnectionPointContainer i IConnectionPoint. Należy jednak zwrócić uwagę na następujące problemy występujące z automatycznie generowanymi implementacjami: Wywoływanie metod klienta odbywa się poprzez funkcje Fire_NazwaMetody(). Wywołanie to odbywa się poprzez interfejs IDispatch, tak więc klient musi zaimplementować interfejs typu [source] wraz z interfejsem IDispatch. Generowany kod dla metod typu Fire_*() w przypadku parametrów typu [out] i [in,out] zawiera błąd. Wymaga to ręcznego poprawienia wygenerowanego kodu, lub modyfikacji w klasie CComVariant. Nie ma odpowiedniego kreatora do tworzenia klienta implementującego interfejs źródłowy.

ATL wizard - błąd w metodzie Fire*() HRESULT Fire_GetValue(FLOAT * Value) CComVariant varresult; T* pt = static_cast<t*>(this); int nconindex; CComVariant* pvars = new CComVariant[1]; int nconnections = m_vec.getsize(); for (nconidx = 0; nconidx < nconnections; nconidx++) pt->lock(); CComPtr<IUnknown> sp = m_vec.getat(nconnectionindex); pt->unlock(); IDispatch* pdispatch = reinterpret_cast<idispatch*>(sp.p); if (pdispatch!= NULL) VariantClear(&varResult); pvars[0] = Value; // Brak opratora dla wskaźników do typu TYPE* DISPPARAMS disp = pvars, NULL, 1, 0 ; pdispatch->invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varresult, NULL, NULL); delete[] pvars; return varresult.scode;

ATL wizard - błąd w metodzie Fire*() Rozwiązanie 1: Modyfikacja kodu generowanej metody: HRESULT Fire_GetValue(FLOAT * Value)... if (pdispatch!= NULL) VariantClear(&varResult); pvars[0].vt=vt_byref VT_R4; // Dla innych typów należy właściwie // zidentyfikować typ przez VT_??? pvars[0].byref = Value; DISPPARAMS disp = pvars, NULL, 1, 0 ; pdispatch->invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varresult, NULL, NULL);...

ATL wizard - błąd w metodzie Fire*() Rozwiązanie 2: Uzupełnienie funkcjonalności klasy CComVariant: class CComVariant : public tagvariant... CComVariant(float* pfltsrc) vt = VT_R4 VT_BYREF; byref = pfltsrc; ; CComVariant& operator=(float* pfltsrc) if (vt!= VT_R4 VT_BYREF) InternalClear(); vt = VT_R4 VT_BYREF; byref = pfltsrc; return *this;...

ATL wizard - implementacja klienta Do zaimplementowania interfejsu typu [source] w klasie klienta można posłużyć się gotowymi wzorcami. 1. Za pomocą ATL wizard należy stworzyć nowy projekt typu ATL COM. 2. Należy stworzyć nową klasę, która będzie odbierać wywołania od komponentu (np. CClass). 3. Należy odziedziczyć tę klasę od: public IDispEventImpl<1, CClass,&DIID IEvents, &LIBID_COMPONENTLib,1,0>, gdzie: CClass - realizowana klasa klienta DIID IEvents - IID implementowanego interfejsu [source] LIBID_COMPONENTLib - LIBID biblioteki komponentu 1, 0 - wersja i podwersja biblioteki komponentu

ATL wizard - implementacja klienta 4.W części public klasy klienta należy umieścić blok deklarujący metody obsługujące wywołania od komponentu: HRESULT stdcall GetValue(float* value) *value=a; return S_OK; ; BEGIN_SINK_MAP( CClass ) SINK_ENTRY_EX(1, DIID IEvents, 1, GetValue) END_SINK_MAP() Trzeci parametr deklaracji SINK_ENTRY_EX odpowiada zdefiniowanemu identyfikatorowi metody (atrybut id() metody).

ATL wizard - implementacja klienta 5. Aby klient mógł odbierać wywołania komponentu należy uttworzyć obiekt CClass i wywołać na jego rzecz metodę DispEventAdvise(): IComponentPtr ComponentObj(CLSID_Component); CClass ClientObj; ClientObj.DispEventAdvise(ComponentObj); float res=0.0; res=a->methodgeneratinggetvalue(); ClientObj.DispEventUnadvise(ComponentObj); ComponentObj=NULL;