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



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

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

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.

Obiekty w plikach wykonywalnych, marshaling

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

Technologie COM i ActiveX COM - Component Object Model

Komunikacja i wymiana danych

Microsoft Interface Definition Language

Zdarzenia (events, connection points)

Programowanie komponentowe

Programowanie współbieżne i rozproszone

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

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

Structured storage, Monikers, Running Object Table

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

PARADYGMATY PROGRAMOWANIA Wykład 4

76.Struktura oprogramowania rozproszonego.

UML a kod. C++, Java i C#

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

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Tworzenie aplikacji rozproszonej w Sun RPC

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

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

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

Programowanie obiektowe

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

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

Aplikacje RMI

TEMAT : KLASY DZIEDZICZENIE

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Podstawy programowania skrót z wykładów:

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

Techniki programowania INP001002Wl rok akademicki 2017/18 semestr letni. Wykład 4. Karol Tarnowski A-1 p.

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

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

Programowanie obiektowe

Programowanie w Internecie. Java

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

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

Wykład 8: klasy cz. 4

Wywoływanie metod zdalnych

Multimedia JAVA. Historia

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

Wykład 5 Okna MDI i SDI, dziedziczenie

Zaawansowane aplikacje internetowe - laboratorium

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

Zaawansowane programowanie w C++ (PCP)

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

PARADYGMATY PROGRAMOWANIA Wykład 3

Pola i metody statyczne. Klasy zawierające pola i metody statyczne

Programowanie obiektowe

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Wykład 4: Klasy i Metody

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

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ć

PROGRAMOWANIE NISKOPOZIOMOWE. Struktury w C. Przykład struktury PN.06. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura

Zaawansowane programowanie w C++ (PCP)

Wywoływanie metod zdalnych

Szablony funkcji i klas (templates)

Zdalne uruchamianie obiektów COM

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Praca w środowisku Visual Studio 2008, Visual C

Projektowanie klas c.d. Projektowanie klas przykład

Specyfikacja API Runtime BAS 3.0

Programowanie obiektowe zastosowanie języka Java SE

Dziedziczenie. Tomasz Borzyszkowski

Zaawansowane programowanie w C++ (PCP)

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

Język JAVA podstawy. wykład 2, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

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

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Programowanie obiektowe

Kurs WWW. Paweł Rajba.

Rodzina protokołów TCP/IP. Aplikacja: ipconfig.

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Java Język programowania

MATERIAŁY DO ZAJĘĆ II

Programowanie obiektowe

Wprowadzenie do projektu QualitySpy

Podstawy Programowania Obiektowego

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch

Tworzenie i wykorzystanie usług sieciowych

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Podstawy programowania. Wykład: 12. Struktury, unie, pola bitowe. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

PHP może zostać rozszerzony o mechanizmy dostępu do różnych baz danych:

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

1 Atrybuty i metody klasowe

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Java jako język programowania

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Aplikacje w środowisku Java

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

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

Transkrypt:

Henryk Budzisz ZPORR nr POKL.04.01.01-00-449/08-00 Koszalin 2009

Technologia COM Wprowadzenie COM Interfejsy Technologia COM w Visual C++ Globally Unique Identifiers (GUIDs) Biblioteka COM Tworzenie obiektu COM Inteface IUnknown Definiowanie komponentu nr POKL.04.01.01-00-449/08-00 2

COM co to jest? COM (Component Object Model) jest opracowaną przez Microsoft technologią umożliwiającą efektywną komunikację między aplikacjami Component Object Model definiuje: binarny standard wywoływania funkcji między komponentami, struktury interfejsów udostępnianych przez poszczególne obiekty, mechanizmy jednoznacznej identyfikacji komponentów i ich interfejsów. nr POKL.04.01.01-00-449/08-00 3

Diagram binarnego standard Klient Obiekt komponentowy (instancja komponentu) wskaźnik na VTBL (pole prywatne) wywoływania funkcji VTBL jest wspólna dla wszystkich klientów korzystających z danego komponentu COM Serwer wskaźnik na funkcję1 wskaźnik na funkcję2 wskaźnik na funkcję3 VTBL (tablica funkcji wirtualnych) funkcja1(pobj,arg1,arg2,...) {... } Implementacja komponentu COM zawarta zwykle w bibliotece DLL nr POKL.04.01.01-00-449/08-00 4

Komponenty COM w jednym procesie Technologia COM definiuje sposób współpracy pomiędzy komponentem a jego klientem. W pojedynczym procesie, klient łączy się z komponentem bez pośrednich komponentów. nr POKL.04.01.01-00-449/08-00 5

Komponenty COM w różnych procesach Klient, który chce się skomunikować z komponentem musi skorzystać z pośrednictwa tzw. RPC stubs oraz obiektów Proxy, istniejących po obu stronach połączenia. nr POKL.04.01.01-00-449/08-00 6

Komponenty COM na różnych komputerach Jeżeli klient i komponent rezydują na różnych komputerach, w technologii DCOM (Distributed COM) komunikację międzyprocesorową zastępuje się protokołem sieciowym. nr POKL.04.01.01-00-449/08-00 7

COM Interfejsy Obiekty COM udostępniają swoje funkcje obiektom zewnętrznym za pośrednictwem interfejsów. Interfejs jest zestawem prototypów funkcji składowych komponentu COM (metod). Nazwy interfejsów przyjęło się poprzedzać przedrostkiem I, np.: ILookup Interfejs można zdefiniować na bazie innego interfejsu, czyli zastosować dziedziczenie (ale wyłącznie jednobazowe) Interfejs nie posiada własnej implementacji. Każdy komponent może implementować wiele interfejsów - oferować wiele zestawów usług. Klienty (aplikacje lub inne komponenty) odwołują się do interfejsów za pośrednictwem wskaźników. Każdy interfejs posiada własny, unikalny identyfikator - Globally Unique Identifier (GUID). nr POKL.04.01.01-00-449/08-00 8

Interfejsy Schemat implementacji interfejsu Każdy komponent może implementować wiele interfejsów - oferować wiele zestawów usług. IA IB Komponent COM (coclass) IC Komponent lub coclass (skrót od component object class) zawiera kod wszystkich funkcji udostępnianych przez interfejsy, funkcje pomocnicze i dane. Komponent jest umieszczony w serwerze COM - pliku binarnym (DLL lub EXE). nr POKL.04.01.01-00-449/08-00 9

Implementacja interfejsu Implementacja interfejsu (definicja komponentu) może być zrealizowana w różnych językach programowania. Komponenty mogą być używane przez inne komponenty lub aplikacje realizowane w różnych językach programowania. Technologia COM definiuje standardy komunikowania się na poziomie binarnym. Na poziomie źródłowym ta sama funkcja będzie kodowana zgodnie ze składnią danego języka, np.: Visual Basic object.add( Time As Double, Name As String ) As Variant C++ HRESULT Add( double Time, BSTR Name, VARIANT* pval ); Java public com.ms.com.variant Add( double Time, String Name ); Trzeba ponadto zapewnić konwersję typów danych. Szczegóły w dokumentacji MSDN (COM Language Translation). nr POKL.04.01.01-00-449/08-00 10

Technologia COM w Visual C++ Preferowanym językiem implementacji jest C++. Interfejs jest definiowany jako klasa abstrakcyjna z czystymi funkcjami wirtualnymi. Do tworzonych obiektów automatycznie dołączana jest Vtable (tablica wywołań funkcji wirtualnych). W C trzeba taką tablicę samemu zdefiniować. Każda metoda musi mieć wskaźnik zwrotny na obiekt. W C++ automatycznie dodawany jest wskaźnik this. W C trzeba dodać do każdej funkcji dodatkowy parametr. Definicja klasy stanowi też automatycznie przestrzeń nazw dla składowych. nr POKL.04.01.01-00-449/08-00 11

Globally Unique Identifiers (GUIDs) Do identyfikacji każdego interfejsu i każdego komponentu, używany jest unikalny identyfikator (128-bitowa struktura; long + uint + uint + 8*char = 16 bajtów). Plik guiddef.h zawiera definicję struktury opisującej GUID i pomocnicze makrodefinicje, np.: DEFINE_GUID. Programista zamiast tego identyfikatora używa związanej z nim stałej symbolicznej IID_<nazwa interfejsu> lub CLSID_<nazwa komponentu>. Przykład definicji stałej IID_ILOOKUP: DEFINE_GUID(IID_ILOOKUP, 0xc4910d71, 0xba7d, 0x11cd, 0x94, 0xe8, 0x08, 0x00, 0x17, 0x01, 0xa8, 0xa3); Do generowania GUID udostępnione są programy narzędziowe (w Visual C++ Tools/Create GUID) oraz funkcja CoCreateGuid z COM API. nr POKL.04.01.01-00-449/08-00 12

Obsługa błędów Wszystkie funkcje COM w Visual C++ (z wyjątkiem AddRef i Release z interfejsu IUnknown) zwracają jako wynik wartość typu HRESULT zawierającą informacje o błędach (plik winerror.h wiersz 17 040). Typowy schemat obsługi błędów: HRESULT hr; hr = funkcja_com(parametry); if (hr == S_OK) { } // dalsze operacje... else cerr << Wywołanie funkcja_com nie powiodło się ; nr POKL.04.01.01-00-449/08-00 13

Makrodefinicje do obsługi błędów Powszechną praktyką jest wykorzystywanie do obsługi błędów makrodefinicji SUCCEEDED i FAILED, którym przekazuje się wynik wywołania funkcji typu HRESULT. Przykład: if ( FAILED( CoInitialize(NULL) )) { cerr << "Inicjacja nie powiodła się"; return 1; } Kod błędu można odczytać z HRESULT stosując makrodefinicję HRESULT_CODE. Opis tekstowy błędu (na podstawie jego kodu, np.: 0x800401F0) można uzyskać przy użyciu narzędzia Tools/Error Lookup w VC++. Opis jest widoczny również w debuggerze. nr POKL.04.01.01-00-449/08-00 14

Biblioteka COM COM library API udostępnia funkcje i makra do obsługi zadań związanych z definiowaniem i używaniem obiektów COM. Bibliotekę trzeba przed użyciem zainicjować przy użyciu funkcji HRESULT CoInitialize(LPVOID pvreserved); Schemat inicjacji: // Inicjacja biblioteki COM - załadowanie plików DLL. if ( FAILED( CoInitialize(NULL) )) { cerr << "Inicjacja biblioteki COM nie powiodła się" << endl; return 1; }... // Zwolnij zasoby przydzielone bibliotece COM. CoUninitialize(); nr POKL.04.01.01-00-449/08-00 15

Tworzenie obiektu COM Aby otworzyć obiekt COM i uzyskać wskaźnik na interfejs stosuje się funkcję CoCreateInstance() z COM API HRESULT CoCreateInstance( REFCLSID rclsid, LPUNKNOWN punkouter, DWORD dwclscontext, REFIID riid, LPVOID* ppv); Parametry: rclsid identyfikator komponentu, np.: CLSID_ShellLink. punkouter używany przy agregacji obiektu COM (NULL gdy nie jest stosowana agregacja) dwclscontext rodzaj serwera; dla serwera DLL w tym samym procesie stosuje się stałą CLSCTX_INPROC_SERVER. riid - identyfikator interfejsu, np.: IID_IShelLink. ppv - wskaźnik na interfejs; parametr zwrotny funkcji. Zwracane wartości: S_OK, REGDB_E_CLASSNOTREG, CLASS_E_NOAGGREGATION lub E_NOINTERFACE. nr POKL.04.01.01-00-449/08-00 16

Interfejs IUnknown Podstawowym interfejsem implementowanym przez każdy obiekt COM jest interfejs IUnknown, udostępniający trzy funkcje: QueryInterface, AddRef, Release. IUnknown Komponent COM QueryInterface AddRef Release implementacja implementacja implementacja nr POKL.04.01.01-00-449/08-00 17

IUnknown funkcje AddRef i Release Funkcje AddRef i Release zarządzają licznikiem referencji do interfejsów. AddRef jest wywoływana, gdy klient używa danego interfejsu i zwiększa licznik o 1. Release jest wywoływana, gdy klient nie potrzebuje już interfejsu i zmniejsza licznik. Obie zwracają nową wartość licznika referencji. Funkcja QueryInterface zostanie omówiona w dalszej części wykładu. nr POKL.04.01.01-00-449/08-00 18

Schemat tworzenia i użycia obiektu COM HRESULT hr; // zmienna przechowująca wynik wywołania IShellLink* pisl; // wskaźnik na interfejs hr = CoCreateInstance ( CLSID_ShellLink, NULL, // CLSID komponentu // nie używa się agregacji CLSCTX_INPROC_SERVER, // typ serwera IID_IShellLink, (void**) &pisl ); if ( SUCCEEDED ( hr ) ) { } // IID interfejsu // zwracany wskaźnik // Wywołania metod komponentu z użyciem pisl... else { } pisl->release(); // powiadom obiekt COM o zakończeniu // Nie utworzono obiektu COM; hr zawiera kod błędu nr POKL.04.01.01-00-449/08-00 19

Przykład użycia komponentu Active Desktop Active Desktop jest usługą Internet Explorera pozwalającą na wyświetlanie stron www, dokumentów HTML, apletów Javy i komponentów ActiveX na tapecie (bez użycia przeglądarki; Uwaga! Spowalnia system). Działania zrealizowane w przykładzie: 1. Inicjalizacja biblioteki COM (funkcja CoInitialize). 2. Utworzenie obiektu COM typu ActiveDesktop i pobranie wskaźnika do interfejsu IActiveDesktop. 3. Wywołanie metody GetWallpaper() komponentu ActiveDesktop. 4. Jeżeli wywołanie zakończyło się powodzeniem wydrukowanie nazwy pliku przechowującego tapetę widoczną na pulpicie. 5. Pobranie przy użyciu metody GetDesktopItemCount() liczby elementów (stron www dodanych do listy) wydruk informacji. 6. Pobranie (w pętli) informacji o elementach (funkcja GetDesktopItem) do struktury COMPONENT i wydruk nazw elementów (stron www). 7. Zwolnienie interfejsu (funkcja Release) 8. Zwolnienie zasobów przydzielonych bibliotece COM (funkcja CoUninitialize). Przykład: solution: Pulpit, project: Pulpit1 nr POKL.04.01.01-00-449/08-00 20

Łaocuchy w technologii COM uzupełnienie przykładu Łańcuchy zwracane przez funkcje COM kodowane są w Unikodzie (2 bajty na znak). Znak w Unikodzie definiowany jest w VC++ przez typ WCHAR, np.: char tekst1[80]; // zwykła tablica znakowa WCHAR tekst2[80]; // tablica znaków w Unikodzie Do przekształcenia tekstu Unikod na tekst ASCII służy funkcja WideCharToMultiByte(). Prostszym sposobem jest użycie klasy CString z biblioteki MFC, której konstruktor akceptuje zarówno łańcuchy ASCII jak i Unikod (konwersja polskich znaków jest poprawna), np.: CString str1(unicode_text); Strumień standardowy wcout akceptuje teksty wyłącznie w Unikodzie. Zwykły tekst musi być przekształcony w Unikod (prefiks L, np.: L Nazwa: ). Uwaga: nie radzi sobie z polskimi znakami przerywa wyprowadzanie. nr POKL.04.01.01-00-449/08-00 21

IUnknown funkcja QueryInferface Funkcja QueryInterface dostępna w każdym komponencie (ponieważ zdefiniowana jest w interfejsie IUnknown) pozwala na uzyskanie dostępu do innych interfejsów danego obiektu. Jej składnia jest następująca: HRESULT QueryInterface (REFIID iid, void** ppvobject); Parametry: iid - identyfikator GUID żądanego interfejsu ppvobject - wskaźnik do żądanego interfejsu; parametr zwrotny. Gdy interfejs jest dostępny, funkcja zwraca wartość S_OK. W przypadku, gdy interfejs nie jest zaimplementowany zwracana jest wartość E_NOINTERFACE. nr POKL.04.01.01-00-449/08-00 22

Przykład użycia komponentu z wieloma interfejsami Zadaniem programu (project: Pulpit2) jest dodanie na pulpicie skrótu do własnego pliku exe. Etapy realizacji zadania: 1. Pobranie ścieżki do własnego pliku exe (GetModuleFileName). 2. Pobranie ścieżki do foldera pulpitu (SHGetSpecialFolderPath). 3. Uzupełnienie ścieżki o nazwę pliku typu.lnk zawierającego link. 4. Sprawdzenie czy plik już istnieje (CFile::GetStatus). 5. Przekształcenie ścieżki z nazwą pliku na łańcuch w Unikodzie (MultiByteToWideChar). 6. Inicjacja biblioteki COM (CoInitialize). 7. Utworzenie obiektu COM typu Shell Link (CoCreateInstance) i uzyskanie wskaźnika na interfejs IShellLink. 8. Ustawienie ścieżki do pliku, dla którego tworzony jest skrót (IShellLink::SetPath) 9. Uzyskanie wskaźnika na kolejny interfejs IPersistFile obiektu Shell Link (IShellLink::QueryInterface) 10. Zapisanie pliku skrótu do foldera pulpitu (IPersistFile::Save) 11. Zwolnienie interfejsów IPersistFile i IShellLink (Release) oraz CoUninitialize nr POKL.04.01.01-00-449/08-00 23

Definiowanie komponentu COM Definiowanie interfejsu Makra i typy danych stosowane w definicjach Implementacja interfejsu nr POKL.04.01.01-00-449/08-00 24

Definiowanie interfejsu Każdy interfejs komponentu COM musi być bezpośrednio lub pośrednio wyprowadzony z interfejsu IUnknown. Interfejs jest definiowany w języku IDL (Microsoft Interface Definition Language). Przykład: import "unknwn.idl"; // definicja interfejsu IUnknown [ object, uuid(4411b7fe-ee28-11ce-9054-080036f12502) ] interface ISome : IUnknown { HRESULT SomeMethod(void); }; [ object, uuid(4411b7fd-ee28-11ce-9054-080036f12502) ] interface ISomeOther : ISome { HRESULT SomeOtherMethod([in]long l); }; Definicja interfejsu zapisywana jest w pliku.idl nr POKL.04.01.01-00-449/08-00 25

Definiowanie interfejsu w VC++ W SDK VC++ dostępna jest klasa IUnknown (plik nagłówkowy unknown.h) reprezentująca interfejs IUnknown. Z klasy tej można wyprowadzić własny interfejs stosując składnię C++, np.: // {15038B10-3D3E-11ce-9EE5-00AA004231BF} DEFINE_GUID(IID_IPrintInterface, 0x15038b10, 0x3d3e, 0x11ce, 0x9e, 0xe5, 0x0, 0xaa, 0x0, 0x42, 0x31, 0xbf); class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions virtual HRESULT QueryInterface(REFIID riid, LPVOID ppvobj)=0; virtual ULONG AddRef(void) = 0; virtual ULONG Release(void) = 0; // This interface virtual HRESULT PrintObject(void) = 0; }; nr POKL.04.01.01-00-449/08-00 26

Makra i typy danych stosowane w definicjach typedef struct _GUID { unsigned long Data1; // 32 bity unsigned short Data2; // 16 bitów unsigned short Data3; // 16 bitów byte Data4[ 8 ]; // 8*8 = 64 bity } GUID; // definicja Globally Unique Identifier, 128 bitów typedef GUID IID - identyfikator interfejsu; synonim GUID typedef IID* LPIID; - wskaźnik daleki na ID interfejsu #define REFIID const IID& - referencja na identyfikator interfejsu typedef GUID CLSID - identyfikator co-klasy; synonim GUID typedef CLSID* LPCLSID; - wskaźnik daleki na ID co-klasy typedef long HRESULT; - typ wyniku funkcji COM; synonim long nr POKL.04.01.01-00-449/08-00 27

Konwencja wywoływania metod interfejsu W Microsoft C++ wprowadzono kilkanaście dodatkowych słów kluczowych (rozpoczynających się od ), które służą do sterowania kompilacją. Słowo kluczowe stdcall określa sposób wywołania wymagany przez funkcje Win32 API. class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions virtual HRESULT stdcall QueryInterface(REFIID riid, LPVOID ppvobj)=0; virtual ULONG stdcall AddRef(void) = 0; virtual ULONG stdcall Release(void) = 0; // This interface virtual HRESULT stdcall PrintObject(void) = 0; }; nr POKL.04.01.01-00-449/08-00 28

Makrodefinicja STDMETHODCALLTYPE Definicja: #ifdef _WIN32 // Win32 doesn't support export #define STDMETHODCALLTYPE stdcall #else #define STDMETHODCALLTYPE export stdcall #endif class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID ppvobj)=0; virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; virtual ULONG STDMETHODCALLTYPE Release(void) = 0; // This interface virtual HRESULT STDMETHODCALLTYPE PrintObject(void) = 0; }; nr POKL.04.01.01-00-449/08-00 29

Makra STDMETHODIMP_ oraz STDMETHODIMP #define STDMETHODIMP HRESULT STDMETHODCALLTYPE #define STDMETHODIMP_(type) type STDMETHODCALLTYPE Pierwsze makro definiuje konwencję i wynik wywołania HRESULT, drugie podany typ wyniku. Przykład: class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID ppvobj)=0; virtual STDMETHODIMP_(ULONG) AddRef(void) = 0; virtual STDMETHODIMP_(ULONG) Release(void) = 0; // This interface virtual STDMETHODIMP PrintObject(void) = 0; }; nr POKL.04.01.01-00-449/08-00 30

Makra STDMETHOD_ i STDMETHOD #define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method #define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method Pierwsza wersja definiuje funkcję wirtualną interfejsu, która zwraca wynik typu HRESULT. Druga definiuje funkcję, która zwraca wynik wskazanego typu. class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions STDMETHOD(QueryInterface)(REFIID riid, LPVOID ppvobj)=0; STDMETHOD_(ULONG, AddRef)(void) = 0; STDMETHOD_(ULONG, Release)(void) = 0; // This interface STDMETHOD(PrintObject)(void) = 0; }; nr POKL.04.01.01-00-449/08-00 31

Makrodefinicja PURE Definiuje czystą funkcję wirtualną: #define PURE = 0 class IPrintInterface : public IUnknown { public: // Standard IUnknown interface functions STDMETHOD(QueryInterface)(REFIID riid, LPVOID ppvobj) PURE; STDMETHOD_(ULONG, AddRef)(void) PURE; STDMETHOD_(ULONG, Release)(void) PURE; // This interface STDMETHOD(PrintObject)(void) PURE; }; nr POKL.04.01.01-00-449/08-00 32

Implementacja interfejsu W C++ interfejs jest implementowany przez klasę. Przykład: class CPrintObject : public IPrintInterface { public: CPrintObject() : refcount(0) {} // konstruktor virtual ~CPrintObject() {} // destruktor // Standardowe funkcje interfejsu IUnknown virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID ppvobj); virtual STDMETHODIMP_(ULONG) AddRef(void); virtual STDMETHODIMP_(ULONG) Release(void); // Funkcje interfejsu IPrintInterface virtual STDMETHODIMP PrintObject(void); protected: CPrintObject(); ULONG refcount; // licznik referencji }; Metody już nie są czystymi funkcjami wirtualnymi i muszą zostać zdefiniowane. nr POKL.04.01.01-00-449/08-00 33

Definicja funkcji AddRef i Release Funkcje AddRef i Release zarządzają licznikiem referencji. Każde użycie interfejsu powoduje zwiększenie stanu licznika (wywołanie AddRef), a kiedy już nie jest potrzebny aplikacja klienta ma obowiązek wywołać funkcję Release. STDMETHODIMP_(ULONG) CPrintObject::AddRef(void) { return ++refcount; // zwiększa licznik referencji } STDMETHODIMP_(ULONG) CPrintObject:: Release(void) { if (--refcount == 0) delete this; // usunięcie obiektu!!! return refcount; } nr POKL.04.01.01-00-449/08-00 34

Funkcja QueryInterface Zadaniem funkcji jest zwrócenie wskaźnika na interfejs o podanym identyfikatorze GUID. Przykład użycia funkcji (założenie: punk jest wskaźnikiem na obiekt IUnknown): IPrintInterface* pprint = NULL; if (punk->queryinterface(iid_iprintinterface, { } (void**)&pprint) == NOERROR) pprint->printobject(); pprint->release(); // release pointer obtained via QueryInterface! nr POKL.04.01.01-00-449/08-00 35

Definicja QueryInterface STDMETHODIMP CPrintObject::QueryInterface(REFIID iid, void FAR* FAR* ppvobj) { } if (iid == IID_IUnknown iid == IID_IPrintInterface) { } *ppvobj = this; AddRef(); // zwiększenie licznika referencji return NOERROR; return E_NOINTERFACE; // zgłoszenie błędu nr POKL.04.01.01-00-449/08-00 36