// LISTING #2 DRUGIE PODEJŚCIE

Wielkość: px
Rozpocząć pokaz od strony:

Download "// LISTING #2 DRUGIE PODEJŚCIE"

Transkrypt

1 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK LISTING #1 PIERWSZE PODEJŚCIE LISTING #2 DRUGIE PODEJŚCIE #include <iostream.h> #include <objbase.h> interfejs A interface IA virtual void stdcall fa() = 0; ; interfejs B interface IB virtual void stdcall fb() = 0; ; Składnik class CMyComp : public IA, public IB Implementacja interfejsu A virtual void stdcall fa(); Implementacja interfejsu B virtual void stdcall fb(); ; void CMyComp::fa() cout << "Jestem fa" << endl; void CMyComp::fb() cout << "Jestem fb" << endl; / Plik nagłówkowy interface.h #include <objbase.h> interfejs A interface IA : public IUnknown virtual void stdcall fa() = 0; ; interfejs B interface IB : public IUnknown virtual void stdcall fb() = 0; ; deklaracje identyfikatorów IID extern const IID IID_IA; extern const IID IID_IB; deklaracja funkcji tworzącej egzemplarz składnika IUnknown *CreateInstance(); / Definicja identyfikatorów IID 033E7EC7-50FA-404c-9C59-4CBA8892F054 static const GUID IID_IA = 0x33e7ec7, 0x50fa, 0x404c, 0x9c, 0x59, 0x4c, 0xba, 0x88, 0x92, 0xf0, 0x54 ; FD854FCC-6AE BB60-DC276E5DFC68 static const GUID IID_IB = 0xfd854fcc, 0x6ae2, 0x4876, 0xbb, 0x60, 0xdc, 0x27, 0x6e, 0x5d, 0xfc, 0x68 ; void main() CMyComp *pcomp = new CMyComp; wskaźnik do interfejsu A IA *pia = pcomp; pia->fa(); wskaźnik do interfejsu B IB *pib = pcomp; pib->fb(); delete pcomp; 1

2 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK / Aplikacja kliencka #include "interface.h" void main() inicjalizacja składnika IUnknown *punknown = CreateInstance(); IUnknown *CreateInstance() IUnknown *p = (IA*)new CMyComp; p->addref(); return p; chcemy skorzystać z interfejsu IA IA *pia = NULL; HRESULT hr = punknown->queryinterface(iid_ia, (void**)&pia); if (SUCCEEDED(hr)) pia->fa(); pia->release(); chcemy skorzystać z interfejsu IB IB *pib = NULL; hr = punknown->queryinterface(iid_ib, (void**)&pib); if (SUCCEEDED(hr)) pib->fb(); pib->release(); punknown->release(); delete punknown; / Moduł składnika #include "interface.h" #include <iostream.h> Klasa składnika class CMyComp : public IA, public IB Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu A virtual void stdcall fa() cout << "Jestem fa" << endl; HRESULT _stdcall CMyComp::QueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (IA*)this; else if (iid == IID_IA) *ppv = (IA*)this; else if (iid == IID_IB) *ppv = (IB*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG _stdcall CMyComp::AddRef() return InterlockedIncrement(&m_nRef); ULONG _stdcall CMyComp::Release() if (InterlockedDecrement(&m_nRef) == 0) delete this; return 0; return m_nref; Implementacja interfejsu B virtual void stdcall fb() cout << "Jestem fb" << endl; public: CMyComp() : m_nref(0) private: long m_nref; ; 2

3 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK / Aplikacja kliencka - korzystająca z serwera COM LISTING #3 TRZECIE PODEJŚCIE / Plik nagłówkowy interface.h #include <objbase.h> interfejs A interface IA : public IUnknown virtual void stdcall fa() = 0; ; interfejs B interface IB : public IUnknown virtual void stdcall fb() = 0; ; deklaracje identyfikatorów IID extern const IID IID_IA; extern const IID IID_IB; #include "interface.h" void main() inicjalizacja podsystemu COM CoInitialize(NULL); inicjalizacja składnika IUnknown *punknown = NULL; HRESULT hr = CoCreateInstance(CLSID_Component, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&punknown); if (SUCCEEDED(hr)) chcemy skorzystać z interfejsu IA IA *pia = NULL; hr = punknown->queryinterface(iid_ia, (void**)&pia); if (SUCCEEDED(hr)) pia->fa(); pia->release(); / Definicja identyfikatorów IID 59F1DE0D a57-82CE-D6DBA3D28D28 static const GUID CLSID_Component = 0x59f1de0d, 0x8843, 0x4a57, 0x82, 0xce, 0xd6, 0xdb, 0xa3, 0xd2, 0x8d, 0x28 ; 033E7EC7-50FA-404c-9C59-4CBA8892F054 static const GUID IID_IA = 0x33e7ec7, 0x50fa, 0x404c, 0x9c, 0x59, 0x4c, 0xba, 0x88, 0x92, 0xf0, 0x54 ; FD854FCC-6AE BB60-DC276E5DFC68 static const GUID IID_IB = 0xfd854fcc, 0x6ae2, 0x4876, 0xbb, 0x60, 0xdc, 0x27, 0x6e, 0x5d, 0xfc, 0x68 ; dalej jak w listingu #2 punknown->release(); / Moduł składnika (serwer) #include "interface.h" #include <iostream.h> #include "registry.h" narzędzia do rejestru systemowego... Zmienne globalne static HMODULE g_hmodule = NULL; uchwyt modułu DLL static long g_ccomponents = 0 ; Licznik aktywnych składników static long g_cserverlocks = 0 ; Licznik dla LockServer Dane do rejestru systemowego const char g_szprogid[] = "COMLecture.Approach3.1"; const char g_szfriendlyname[] = "Wykład z COM, podejście 3"; const char g_szverindprogid[] = "COMLecture.Approach3"; 3

4 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Klasa składnika Class Factory class CMyComp : public IA, public IB public: Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu A virtual void stdcall fa() cout << "Jestem fa" << endl; Implementacja interfejsu B virtual void stdcall fb() cout << "Jestem fb" << endl; public: CMyComp() : m_nref(1) InterlockedIncrement(&g_cComponents); ~CMyComp() InterlockedDecrement(&g_cComponents); private: long m_nref; ; HRESULT _stdcall CMyComp::QueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (IA*)this; else if (iid == IID_IA) *ppv = (IA*)this; else if (iid == IID_IB) *ppv = (IB*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG _stdcall CMyComp::AddRef() return InterlockedIncrement(&m_nRef); ULONG _stdcall CMyComp::Release() if (InterlockedDecrement(&m_nRef) == 0) delete this; return 0; return m_nref; class CFactory : public IClassFactory public: Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu IClassFactory virtual HRESULT stdcall CreateInstance( IUnknown* punknownouter, const IID& iid, void** ppv); virtual HRESULT stdcall LockServer(BOOL block); CFactory() : m_nref(1) private: long m_nref ; ; Class Factory interfejs IUnknown HRESULT stdcall CFactory::QueryInterface(const IID& iid, void** ppv) if ((iid == IID_IUnknown) (iid == IID_IClassFactory)) *ppv = (IClassFactory*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG stdcall CFactory::AddRef() return InterlockedIncrement(&m_nRef) ; ULONG stdcall CFactory::Release() if (InterlockedDecrement(&m_nRef) == 0) delete this ; return 0 ; return m_nref ; 4

5 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Class Factory interfejs IClassFactory Funkcje eksportowane! HRESULT stdcall CFactory::CreateInstance(IUnknown* punknownouter, const IID& iid, void** ppv) if (punknownouter!= NULL) return CLASS_E_NOAGGREGATION; Utworzenie składnika CMyComp* pmycomp = new CMyComp; if (!pmycomp) return E_OUTOFMEMORY; Utworzenie żądanego interfejsu HRESULT hr = pmycomp->queryinterface(iid, ppv); pmycomp->release(); return hr; HRESULT stdcall CFactory::LockServer(BOOL block) if (block) InterlockedIncrement(&g_cServerLocks) ; else InterlockedDecrement(&g_cServerLocks) ; return S_OK ; Inicjalizacja DLL BOOL APIENTRY DllMain(HMODULE hmodule, DWORD ul_reason_for_call, LPVOID lpreserved) if (ul_reason_for_call == DLL_PROCESS_ATTACH) g_hmodule = hmodule; return TRUE ; STDAPI DllCanUnloadNow() if ((g_ccomponents == 0) && (g_cserverlocks == 0)) else return S_FALSE; STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) Czy możemy utworzyć taki składnik? if (clsid!= CLSID_Component) return CLASS_E_CLASSNOTAVAILABLE ; Utwórz fabrykę klas CFactory* pfactory = new CFactory; if (pfactory == NULL) return E_OUTOFMEMORY; Zwróć żądany interfejs HRESULT hr = pfactory->queryinterface(iid, ppv); pfactory->release(); return hr; STDAPI DllRegisterServer() return RegisterServer(g_hModule, CLSID_Component, g_szfriendlyname, g_szverindprogid, g_szprogid); STDAPI DllUnregisterServer() return UnregisterServer(CLSID_Component, g_szverindprogid, g_szprogid); / Plik COMPONENT.DEF LIBRARY Component.dll DESCRIPTION 'Przykład do wykładu COM, (C) Jarosław Francik 2001' EXPORTS PRIVATE PRIVATE PRIVATE PRIVATE 5

6 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK / Aplikacja kliencka - korzystająca z serwera COM LISTING #4 CZWARTE PODEJŚCIE (SERWER EXE) / Specyfikacja mytypes.idl import "unknwn.idl"; Interface IA [ object, uuid(b5db b7db-30da5e75d347), helpstring("ia Interface"), pointer_default(unique) ] interface IA : IUnknown HRESULT fa(); ; Interface IB [ object, uuid(10ae43a2-2d3f-48a9-8ed3-d3f1f21cc898), helpstring("ib Interface"), pointer_default(unique) ] interface IB : IUnknown HRESULT fb(); ; Biblioteka typów + clsid składników [ uuid(3221ccff-68b2-442b-afdc-fa9c767f1fc4), version(1.0), helpstring("biblioteka typów Approach3a") ] library MyTypeLib importlib("stdole32.tlb") ; [ uuid(e843265d-b374-4d56-a980-0ec5e9188b47), helpstring("klasa komponentu Approach3a") ] coclass Component [default] interface IA; interface IB; ; ; #include "..\\mytypes.h" #include "..\\mytypes_i.c" void main() inicjalizacja podsystemu COM CoInitialize(NULL); inicjalizacja składnika IUnknown *punknown = NULL; HRESULT hr = CoCreateInstance(CLSID_Component, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&punknown); / Moduł proxy zawiera wyłącznie pliki utworzone przez midl: dlldata.c, abc_i.c, abc_p.c, linkowane z rpcndr.lib, rpcns4.lib i rpcrt4.lib Oto plik PROXY.DEF: LIBRARY proxy.dll DESCRIPTION 'Przykład do wykładu COM, (C) Jarosław Francik 2001' EXPORTS PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE / Moduł składnika (serwer) #include "..\\mytypes.h" #include "..\\mytypes_i.c" #include <iostream.h> #include <memory.h> #include "registry.h" narzędzia do rejestru systemowego... Zmienne globalne usunieto zmienną g_hmodule ponadto jak w podejściu Trzecim 6

7 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Klasa składnika class CMyComp : public IA, public IB public: Implementacja interfejsu IUnknown jak w Podejściu Trzecim Implementacja interfejsu A virtual HRESULT stdcall fa() MessageBox(0, "Jestem fa", "Jestem fa", 0); Implementacja interfejsu B virtual HRESULT stdcall fb() MessageBox(0, "Jestem fb", "Jestem fb", 0); public: CMyComp() : m_nref(1) InterlockedIncrement(&g_cComponents); ~CMyComp() InterlockedDecrement(&g_cComponents); if (g_ccomponents == 0 && g_cserverlocks == 0) PostQuitMessage(0); private: long m_nref; ; Implementacja klasy CMyComp jak w Podejściu Trzecim Class Factory Deklaracja i implementacja fabryki klas jak w Podejściu Trzecim; jedyna różnica dotyczy poniższej funkcji: HRESULT stdcall CFactory::LockServer(BOOL block) if (block) InterlockedIncrement(&g_cServerLocks); else InterlockedDecrement(&g_cServerLocks); if (g_ccomponents == 0 && g_cserverlocks == 0) PostQuitMessage(0); return S_OK ; Część aplikacyjna + obsługa COM LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) Inicjalizacja COM flaga określająca tryb pracy bool bembedding = false; Inicjalizacja COM HRESULT hr = CoInitialize(NULL) ; if (FAILED(hr)) return 0 ; Odczyt linii wywołania char sztokens[] = "-/"; char* sztoken = strtok(lpcmdline, sztokens) ; while (sztoken!= NULL) if (_stricmp(sztoken, "UnregServer") == 0) UnregisterServer(FALSE, CLSID_Component, g_szverindprogid, g_szprogid); CoUninitialize(); return 0; else if (_stricmp(sztoken, "RegServer") == 0) RegisterServer(FALSE, hinstance, CLSID_Component, g_szfriendlyname, g_szverindprogid, g_szprogid); CoUninitialize(); return 0; else if (_stricmp(sztoken, "Embedding") == 0) bembedding = true; break ; sztoken = strtok(null, sztokens); 7

8 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Rejestracja fabryki klas DWORD dregister; CFactory *pfactory = new CFactory; hr = ::CoRegisterClassObject(CLSID_Component, pfactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dregister); if (FAILED(hr)) pfactory->release() ; return FALSE ; / Standardowa część aplikacji if (!bembedding) Rejestracja klasy okna WNDCLASS wc; memset(&wc, 0, sizeof(wc)); wc.lpfnwndproc = (WNDPROC)WndProc; wc.hinstance = hinstance; wc.hcursor = LoadCursor(NULL, IDC_ARROW); wc.hbrbackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszclassname = "my_class1"; RegisterClass(&wc); Utworzenie okna HWND hwnd; hwnd = CreateWindow("my_class1", "Tytuł", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinstance, NULL); if (!hwnd) return FALSE; ShowWindow(hWnd, ncmdshow); UpdateWindow(hWnd); / Końcowa deinicjalizacja systemu COM! CoRevokeClassObject(dRegister); CoUninitialize(); return msg.wparam; Funkcja okienkowa LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) switch (message) case WM_DESTROY: nie pozwala zamknąć aplikacji, dopóki klienci korzystają z serwera if (g_ccomponents == 0 && g_cserverlocks == 0) PostQuitMessage(0); break ; case WM_CLOSE: znosi blokadę na czas używania interfejsu użytkownika ::InterlockedDecrement(&g_cServerLocks); return (DefWindowProc(hWnd, message, wparam, lparam)) ; default: return DefWindowProc(hWnd, message, wparam, lparam); return 0; Blokuje serwer na czas używania interfejsu użytkownika InterlockedIncrement(&g_cServerLocks); Pętla komunikatów MSG msg; while (GetMessage(&msg, NULL, 0, 0)) TranslateMessage(&msg); DispatchMessage(&msg); 8

9 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK / Moduł składnika (serwer) LISTING #5 PIĄTE PODEJŚCIE (DISPINTERFEJSY) / Specyfikacja mytypes.idl import "unknwn.idl"; Interface IA [ object, uuid(b5db b7db-30da5e75d347), helpstring("ia Interface"), pointer_default(unique), dual, oleautomation ] interface IA : IDispatch HRESULT fa(); ; reszta bez zmian / Aplikacja kliencka - korzystająca z interfejsu vtable BEZ ŻADNYCH ZMIAN / Moduł proxy bez zmian rozszerzenie klasy CMyComp obejmuje implementację interfejsu IDispatch class CMyComp : public IA, public IB public: Implementacja interfejsu IDispatch virtual HRESULT stdcall GetTypeInfoCount( UINT RPC_FAR *pctinfo); virtual HRESULT stdcall GetTypeInfo( UINT itinfo, LCID lcid, ITypeInfo RPC_FAR * RPC_FAR *pptinfo); virtual HRESULT stdcall GetIDsOfNames( REFIID riid, LPOLESTR RPC_FAR *rgsznames, UINT cnames, LCID lcid, DISPID RPC_FAR *rgdispid); virtual HRESULT stdcall Invoke( DISPID dispidmember, REFIID riid, LCID lcid, WORD wflags, DISPPARAMS RPC_FAR *pdispparams, VARIANT RPC_FAR *pvarresult, EXCEPINFO RPC_FAR *pexcepinfo, UINT RPC_FAR *puargerr); protected: ITypeInfo *m_pitypeinfo; HRESULT InitTypeInfo(); public: rzeczy pomocne uzupełnienie konstruktora: CMyComp() : m_nref(1) InterlockedIncrement(&g_cComponents); InitTypeInfo(); ; RESZTA BEZ ZMIAN 9

10 OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Funkcja tworząca obiekt informacji o typach Implementacja interfejsu IDispatch opiera się na wykorzystaniu funkcjonalności obiektu informacji o typach HRESULT stdcall CMyComp::GetTypeInfoCount(UINT RPC_FAR *pctinfo) *pctinfo = 1; HRESULT stdcall CMyComp::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo RPC_FAR * RPC_FAR *pptinfo) *pptinfo = NULL; if (itinfo!= 0) return DISP_E_BADINDEX; m_pitypeinfo->addref(); *pptinfo = m_pitypeinfo; HRESULT stdcall CMyComp::GetIDsOfNames(REFIID riid, LPOLESTR RPC_FAR *rgsznames, UINT cnames, LCID lcid, DISPID RPC_FAR *rgdispid) if (riid!= IID_NULL) return DISP_E_UNKNOWNINTERFACE; HRESULT hr; hr = m_pitypeinfo->getidsofnames(rgsznames, cnames, rgdispid); return hr; HRESULT stdcall CMyComp::Invoke( DISPID dispidmember, REFIID riid, LCID lcid, WORD wflags, DISPPARAMS RPC_FAR *pdispparams, VARIANT RPC_FAR *pvarresult, EXCEPINFO RPC_FAR *pexcepinfo, UINT RPC_FAR *puargerr) if (riid!= IID_NULL) return DISP_E_UNKNOWNINTERFACE; HRESULT hr = m_pitypeinfo->invoke((ia*)this, dispidmember, wflags, pdispparams, pvarresult, pexcepinfo, puargerr); return hr; HRESULT CMyComp::InitTypeInfo() HRESULT hr; spróbuj załadować bibliotekę typów z rejestru systemowego ITypeLib *ptypelib = NULL; hr = LoadRegTypeLib(LIBID_MyTypeLib, 1, 0, 0x00, &ptypelib); if (FAILED(hr)) załaduj z pliku ustal nazwę pliku exe i podziel ją na czynniki pierwsze char szmodule[512] ; DWORD dwresult = ::GetModuleFileName(g_hInstance, szmodule, 512); char szdrive[_max_drive]; char szdir[_max_dir]; _splitpath(szmodule, szdrive, szdir, NULL, NULL); Określ nazwę pliku TLB char sztypelibfullname[_max_path]; sprintf(sztypelibfullname, "%s%s%s", szdrive, szdir, "mytypes.tlb"); convert to wide char wchar_t wsztypelibfullname[_max_path]; mbstowcs(wsztypelibfullname, sztypelibfullname, _MAX_PATH); hr = LoadTypeLib(wszTypeLibFullName, &ptypelib); if (FAILED(hr)) return hr; na wszelki wypadek zarejestruj hr = RegisterTypeLib(pTypeLib, wsztypelibfullname, NULL); if (FAILED(hr)) return hr; pobierz TypeInfo dla IA m_pitypeinfo = NULL; hr = ptypelib->gettypeinfoofguid(iid_ia, &m_pitypeinfo); ptypelib->release(); if (FAILED(hr)) return hr; Podnadto uzupełniono CMyComp::QueryInterface tak, by zwracała w razie potrzeby wskaźnik na IDispatch 10

11 Aternatywna Aplikacja kliencka Aplikacja korzysta z dispinterfejsu #include <objbase.h> #include <assert.h> OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK Klient w Visual Basicu: Dim x As Object Set x = CreateObject(COMLecture.Approach5 ) x.fa void main() inicjalizacja podsystemu COM CoInitialize(NULL); wchar_t progid[] = L"COMLecture.Approach5"; CLSID clsid; CLSIDFromProgID(progid, &clsid); / Klient w MFC (po utworzeniu klasy wrapper IA ia; ia.createdispatch("comlecture.approach5"); ia.fa(); IDispatch *pidispatch = NULL; HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pidispatch); assert(succeeded(hr)); DISPID dispid; OLECHAR *name = L"fa"; hr = pidispatch->getidsofnames(iid_null, &name, 1, GetUserDefaultLCID(), &dispid); assert(succeeded(hr)); VARIANTARG varg; VariantInit(&varg); varg.vt = VT_EMPTY; DISPPARAMS param; param.cargs = 0; param.rgvarg = &varg; param.cnamedargs = 0; param.cargs = NULL; hr = pidispatch->invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, NULL, NULL, NULL); assert(succeeded(hr)); 11

12 Wstęp do programowania składnikowego Programowanie składnikowe Złota zasada: Interfejsem jest wszystko CZĘŚĆ 1: składniki i interfejsy Interfejsy lepiej oddają funkcjonalność obiektów niż dziedziczenie Jarosław Francik Założenia: 1. Programowanie składnikowe to sposób programowania (filozofia) 2. COM to tylko jedna ze specyfikacji wspierających programowanie składnikowe 3. W ramach wykładu korzystamy ze zwykłego C++ by tworzyć oprogramowanie składnikowe 4. W miarę potrzeb będziemy wprowadzać elementy COM Pierwsze podejście... Interfejs = klasa abstrakcyjna Składnik = klasa implementująca abstrakcyjny interfejs (dziedzicząca po klasie abstrakcyjnej) Wiele interfejsów = dziedz. wielobazowe #include <iostream.h> interfejs A class IA public: virtual void fa() = 0; ; interfejs B class IB public: virtual void fb() = 0; ; Składnik class CMyComp : public IA, public IB Implementacja interfejsu A virtual void fa(); void CMyComp::fa() cout << "Jestem fa" << endl; void CMyComp::fb() cout << "Jestem fb" << endl; void main() CMyComp *pcomp = new CMyComp; wskaźnik do interfejsu A IA *pia = pcomp; pia->fa(); wskaźnik do interfejsu B IB *pib = pcomp; pib->fb(); Model komunikacji klient-składnik Klient Składnik ; Implementacja interfejsu B virtual void fb(); delete pcomp; 1

13 Pierwsze podejście... Specyfikacja COM nie wymusza stosowania klas C++, jednak: binarny format tablicy funkcji wirtualnych C++ jest zgodny ze specyfikacją COM Pierwsze podejście... Wprowadzamy ułatwienia i wymogi COM: include <objbase.h> interface (słowo kluczowe C++) stdcall konwencja wywołania Pierwsze podejście... [ listing #1 ] Słaby punkt: wykorzystujemy bezpośrednio wskaźnik na klasę komponentu w ten sposób zbyt mocno wiążemy klienta z implementacją składnika Rozwiązanie: stworzyć odrębną funkcję CreateInstance, której implementacja jest wewnętrznym szczegółem modułu składnika Lepsze podejście... Publicznie widzimy: interfejsy deklarację funkcji CreateInstance narzędzie do uzyskiwania wskazanych interfejsów? oczywiście też interfejs: IUnknown 2

14 Wstęp do programowania składnikowego CZĘŚĆ 2: interfejs Iunknown Jarosław Francik Interfejs IUnknown interface IUnknown virtual HRESULT stdcall QueryInterface (const IID &iid, void **ppc) = 0; virtual ULONG stdcall AddRef() = 0; virtual ULONG stdcall Release() = 0; ; Każdy interfejs COM dziedziczy po IUnknown IUnknown::QueryInterface Klient 1. Klient wywołuje QueryInterface(IID) 2. Obiekt zwraca wskaźnik na interfejs 3. Klient może wywoływać metody Składnik COM HRESULT QueryInterface(const IID &iid, void **p); IUnknown::QueryInterface (użycie przez klienta) inicjalizacja składnika IUnknown *pcomp = CreateInstance(); chcemy skorzystać z interfejsu IA IA *pia = NULL; HRESULT hr = pcomp->queryinterface (IID_IA, (void**)&pia); if (SUCCEEDED(hr)) pia->fa(); identyfikator interfejsu IID (GUID) IUnknown::QueryInterface (implementacja) HRESULT _stdcall CMyComp::QueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (IA*)this; else if (iid == IID_IA) *ppv = (IA*)this; else if (iid == IID_IB) *ppv = (IB*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); Funkcja CreateInstance IUnknown *CreateInstance() IUnknown *p = (IA*)new CMyComp; p->addref(); return p; W bibliotece COM API dostępna jest funkcja CoCreateInstance o podobnym działaniu 1

15 Drugie podejście T T Co widzi klient? T interfejsy T identyfikatory interfejsów (IID) T nagłówek funkcji CreateInstance (w COM korzystamy raczej z funkcji bibliotecznej CoCreateInstance) Co implementuje składnik? T klasa implementująca interfejs IUnknown oraz własne interfejsy T funkcja CreateInstance [ listing #2 ] Nie używamy dziedziczenia wirtualnego! Jest ono niezgodne z formatem binarnym COM QueryInterface QueryInterface możemy stosować do dowolnego interfejsu, nie tylko do IUnknown gdyż wszystkie interfejsy dziedziczą po IUnknown QueryInterface IUnknown *p = CreateInstance(); IA *pia = NULL; hr = p->queryinterface(iid_ia, (void**)&pia); if (!SUCCEEDED(hr)) return; Interfejs IB otrzymujemy z IA IB *pib = NULL; hr = pia->queryinterface(iid_ib, (void**)&pib); if (!SUCCEEDED(hr)) return; Interfejs IUnknown otrzymujemy z IB IUnknown * punknown = NULL; hr = pib->queryinterface(iid_iunknown, (void**)&punknown); if (!SUCCEEDED(hr)) return; QueryInterface T T T T Za każdym razem otrzymuję ten sam interfejs IUnknown Zawsze mogę otrzymać interfejs, który już kiedyś uzyskałem Zawsze mogę uzyskać interfejs, który już mam Jeśli mogę otrzymać interfejs gdziekolwiek, to mogę go otrzymać wszędzie 2

16 QueryInterface T definiuje obiekt T pozwala udostępniać różne wersje interfejsów dla tego samego obiektu T pomaga utrzymać kompatybilność wstecz przy wypuszczaniu nowej wersji produktu T ALE: wymaga to dotrzymania założeń przez projektanta nowej wersji!!! Zliczanie referencji: AddRef/Release T Klasa składnika zawiera licznik referencji T AddRef zwiększa licznik T Release zmniejsza licznik i w razie potrzeby usuwa składnik z pamięci T Utworzenie obiektu = AddRef T Porzucenie obiektu = Release Zliczanie referencji: AddRef/Release ULONG _stdcall CMyComp::AddRef() return InterlockedIncrement(&m_nRef); ULONG _stdcall CMyComp::Release() if (InterlockedDecrement(&m_nRef) == 0) delete this; return 0; return m_nref; AddRef/Release: trzy proste zasady T Wywołaj AddRef zanim zwrócisz wynik T jeśli zwracasz interfejs jako wartość funkcji. Dotyczy też QueryInterface i CreateInstance! T Wywołaj Release kiedy skończysz T gdy nie będziesz już dłużej wykorzystywał interfejsu T Wywołaj AddRef gdy robisz przypisanie T AddRef/Release: Optymalizacja Nie musisz stosować AddRef/Release w przypadku użycia wskaźnika o zagnieżdżonym zasięgu (w obrębie zasięgu innego wskaźnika) T T T T T T parametr wejściowy nic (jest zagnieżdżony) parametr wyjściowy AddRef parametr wejściowo-wyjściowy być może AddRef + Release zmienna lokalna nic (jest zagnieżdżona) zmienna globalna AddRef + Release w przypadku wątpliwości AddRef + Release Drugie podejście... T Słaby punkt: T funkcja CreateInstance zbyt mocno wiąże klienta z serwerem T Rozwiązanie: T skorzystamy z technologii COM... 3

17 Wstęp do programowania składnikowego CZĘŚĆ 3: Funkcja CoCreateInstance, fabryki klas i serwery COM Jarosław Francik Podstawy technologii COM HRESULT standardowy typ wartości zwracanych przez funkcje S_OK S_FALSE E_UNEXPECTED E_NOTIMPL E_NOINTERFACE E_OUTOFMEMORY Bity: 0-15 return code co się stało facility code id części systemu 31 sukces czy porażka Makro SUCCEEDED Funkcja FormatMessage Podstawy technologii COM Rejestr Windows HKEY_CLASSES_ROOT CLSID 59F1DE0D A57-82CE-D6DBA3D28D28: Wykład COM, podejście 3 T InProcServer32: c:\windows\system32\component.dll T ProgID: COMLecture.Approach3.1 T VersionIndependentProgID: COMLecture.Approach3 COMLecture.Approach3.1: Wykład COM, podejście 3 CLSID: 59F1DE0D A57-82CE-D6DBA3D28D28 COMLecture.Approach3: Wykład COM, podejście 3 CLSID: 59F1DE0D A57-82CE-D6DBA3D28D28 CurVer: COMLecture.Approach3.1 Podstawy technologii COM Rejestr Windows (c.d.) Przydatne funkcje: CLSIDFromProgID Rejestrowanie serwerów COM Serwer musi sam dostarczyć eksportowanych funkcji: DllRegisterServer DllUnregisterServer Przydatne narzędzia: RegOpenKeyEx, RegCreateKeyEx, RegSetValueEx, RegEnumKeyEx, RegDeleteKey, RegCloseKey Pliki Registry.h i Registry.cpp można znaleźć wraz z programem przykładowym approach3 Podstawy technologii COM Przydatne funkcje: CoInitialize(NULL); dla każdego procesu osobno! CoUninitialize StringFromCLSID StringFromIID CLSIDFromString IIDFromString CoTaskMemAlloc CoTaskMemFree Podstawy technologii COM CoCreateInstance ( const CLSID &clsid, IUnknown *piunknownouter, DWORD dwclscontext, const IID &iid, void **ppv); 1

18 Trzecie podejście - klient Zastępujemy dotychczasowy CreateInstance wywołaniem CoCreateInstance Powiązanie między klientem a serwerem już tylko poprzez CLSID! Trzecie podejście - klient CoInitialize(NULL); IA *pia = NULL; HRESULT hr = CoCreateInstance( CLSID_MyComponent, NULL, CLSCTX_INPROC_SERVER, IID_IA, (void**)&pia); if (SUCCEEDED(hr)) pia->fa(); pia->release(); Fabryka klas IClassFactory interfejs służący do tworzenia egzemplarzy klas (obiektów) interface IClassFactory HRESULT stdcall CreateInstance (IUnknown *punknownouter, const IID& iid, void **ppv); HRESULT stdcall LockServer(BOOL b); w wywołaniu CreateInstance brakuje CLSID Fabryka klas służy do tworzenia obiektów określonej klasy Fabryka klas Funkcja CoGetClassObject zwraca wskaźnik na fabrykę klas dla określonego CLSID HRESULT stdcall CoGetClassObject( const CLSID &clsid, DWORD dwclscontext, COSERVERINFO *pserverinfo, const IID &iid, void **ppv); CoGetClassObject wywołuje DllGetClassObject: funkcję obowiązkowo eksportowaną przez serwery COM Fabryka klas Fabryka klas CoCreateInstance vc CoGetClassObject HRESULT stdcall CoCreateInstance (...) *ppv = NULL; IClassFactory *pfactory = NULL; HRESULT hr = CoGetClassObject(clsid,..., IID_IClassFactory, &pfactory); if (SUCCEEDED(hr)) hr = pfactory->createinstance(..., iid, ppv); pfactory->release; return hr; Klient CoCreateInstance COM API CoGet- ClassObject IA* DLL DllGetClassObject Class Factory new CFactory IClassFactory* IClassFactory::CreateInstance IClassFactory::Release pia->fa Składnik new CMyComp QueryInterface 2

19 Trzecie podejście - serwer Implementacja klasy składnika: prawie bez zmian Implementacja fabryki klas: implementacja IUnknown standardowa implementacja IClassFactory::CreateInstance implementacja IClassFactory::LockServer Implementacja eksportowanych funkcji: DllCanUnloadNow wymaga zliczania instancji DllGetClassObject DllRegisterServer / DllUnRegisterServer [ listing #3 ] Trzecie podejście co dalej? Serwer COM rejestrujemy za pomocą programu regsrv32 Interfejsy mają stałe IID Aplikacje wcale nie muszą korzystać stale z tych samych CLSID 3

20 TWORZENIE SKŁADNIKÓW WEWNĄTRZPROCESOWYCH Poniższy zwięzły opis przedstawia najważniejsze kroki niezbędne dla uzyskania klienta i serwera wewnątrzprocesowego COM. Ilustracją poniższej instrukcji są kody źródłowe approach3 i approach3a, a także inne materiały dostępne na stronie sun.iinf.polsl.gliwice.pl/~jfrancik/lectures/com.html. 1. STWORZENIE SPECYFIKACJI IDL Plik IDL zawiera specyfikację tworzonych interfejsów i klas składników (a także biblioteki typów). Wynikiem kompilacji pliku abc.idl są między innymi pliki abc.h (deklaracje interfejsów w języku C/C++) oraz abc_i.c (definicje identyfikatorów iid i clsid). [Krok ten eliminuje potrzebę tworzenia pliku nagłówkowego interface.h oraz definiowania explicite identyfikatorów iid / clsid por. listing approach 3] 2. STWORZENIE APLIKACJI KLIENCKIEJ Aplikacja kliencka powinna obejmować obydwa pliki wynikowe kompilacji specyfikacji IDL wspomniane w poprzednim punkcie. Aplikacja inicjalizuje system COM (CoInitialize), zakłada nowy egzemplarz składnika za pomocą funkcji CoCreateInstance i otrzymuje wskaźnik na podany interfejs. Wskaźnik na dowolny, inny interfejs aplikacja może otrzymać wywołując funkcję QueryInterface już posiadanego interfejsu. Aplikacja jest zobowiązana wywoływać funkcje AddRef/Release zgodnie z obowiązującymi zasadami (por. prezentacja approach2.pdf). 3. STWORZENIE MODUŁU DLL SERWERA Na stworzenie modułu serwera składają się następujące czynności: 1. Wprowadzenie do projektu plików wynikowych kompilacji specyfikacji IDL wyszczególnionych w p Założenie globalnych liczników: aktywnych składników oraz blokad serwera. 3. Stworzenie klasy składnika. Wszystkie implementowane interfejsy powinny być wyszczególnione jako klasy bazowe. Należy zaimplementować wszystkie funkcje składowe tych interfejsów, a także funkcje składowe interfejsu IUnknown: QueryInterface, AddRef oraz Release. [Użycie specyfikacji IDL wymusza, by wszystkie funkcje składowe zwracały HRESULT. Listing Approach3 nie spełnia tego wymogu; stosowną poprawkę można znaleźć w listingu Approach3a] 4. Stworzenie klasy implementującej interfejs IClassFactory (fabrykę klas). Należy zaimplementować zarówno funkcje składowe interfejsu IClassFactory (CreateInstance i LockServer), jak i wyszczególnione wcześniej funkcje składowe interfejsu IUnknown. 5. Implementacja punktu wejściowego DLL (DllMain). W obrębie tej funkcji należy zachować uchwyt modułu DLL HMODULE. 6. Implementacja obowiązkowych funkcji eksportowanych: - DllCanUnloadNow na podstawie wspomnianych w p. 3-2 globalnych liczników ustala, czy serwer może być usunięty z pamięci. - DllGetClassObject sprawdza podany clsid i tworzy odpowiadającą mu fabrykę klas. Zwraca wskaźnik do wskazanego w parametrze interfejsu fabryki klas. - DllRegisterServer na podstawie zachowanego w funkcji DllMain uchwytu modułu DLL oraz dodatkowych, pomocniczych zmiennych globalnych, przeprowadza rejestrację serwera. Pomocne są tu pliki registry.h i registry.cpp ( Dale Rogerson) zawierające pomocne funkcje. - DllUnregisterServer na podstawie dodatkowych, pomocniczych zmiennych globalnych, przeprowadza wyrejestrowanie serwera. Pomocne są tu pliki registry.h i registry.cpp ( Dale Rogerson) zawierające pomocne funkcje. 7. Rejestracja modułu w systemie (za pomocą opcji Tools Register Control w Visual Studio lub wywołując program regsvr32). opracowanie: Jarosław Francik

21 IDL EKSPRESOWE WPROWADZENIE Jarosław Francik PRZYKŁAD DEFINICJI INTERFEJSU: OBJAŚNIENIA: import "unknwn.idl"; [ object, uuid(b5db b7db-30da5e75d347), helpstring("przykładowy interfejs IA"), pointer_default(unique) ] interface IA : IUnknown HRESULT fun([in] int x, [out] int &r); ; Powyższa definicja odpowiada następującej klasie C++: interface IA : public IUnknown virtual void stdcall fa() = 0; ; Specyfikacja klasy jest poprzedzona fragmentem znajdującym się w nawiasach kwadratowych. Są to rozszerzenia IDL w stosunku do C++: import wstawia plik w IDL (w tym przypadku: definicję klasy IUnknown) object wyróżnik obiektu COM (IDL ma zastosowania szersze niż tylko COM) uuid identyfikator GUID helpstring zwięzły opis w języku naturalnym, udostępniany na poziomie biblioteki typów pointer_default domyślny tryb marshalingu wskaźników; dostepne wartości to: ref wskaźniki są traktowane jak referencje: nie mogą zawierać NULL, nie mogą być zmieniane, w obrębie funkcji nie mogą być tworzone aliasy unique wskaźniki mogą zawierać NULL, mogą być zmieniane, ale w obrębie funkcji nie mogą być tworzone aliasy ptr wszystko powyższe jest dozwolone Specyfikacja funkcji składowych. Wszystkie funkcji w IDL muszą zwracać wartość HRESULT. Poszczególne parametry mogą zawierać dodatkowe określniki, stanowiące rozszerzenia IDL w stosunku do C++. Są one niezbędne dla zapewnienia prawidłowego marshalingu parametrów. Do zdefiniowania parametrów marshalingu są potrzebne: adres przesyłanej zmiennej, kierunek przesyłu argumentu, rozmiar przesyłanego bloku. Pierwszy z powyższych parametrów jest znany podczas wykonania programu. Kierunek przesyłu argumentu określa się za pomocą następujących określników: in out in, out wyróżnik argumentu wejściowego funkcji wyróżnik argumentu wyjściowego (wyniku) funkcji (na ogół wskaźnika lub referencji) wyróżnik argumentu będącego jednocześnie wejściowym i wyjściowym Rozmiar przesyłanego bloku jest najczęściej jednoznacznie określany na podstawie typu przesyłanych danych. W kolejnych podpunktach zostaną przedstawione elementy języka IDL pozwalające na określenie rozmiaru przesyłanych danych w przypadkach, gdy nie może on być ustalony tylko na podstawie typu danych. Przesyłanie łańcuchów wymaga użycia określnika string. Należy pamiętać, że COM obsługuje wyłącznie łańcuchy Unicode (wchar_t zamiast char): HRESULT strfun([in, string] wchar_t *pin, [out, string] wchar_t **pout);

22 Przesyłanie tablic wymaga określenia rozmiaru tablicy za pomocą określnika size_is. Pozwala on na podanie rozmiaru posługując się innym parametrem, który powinien zawierać rozmiar tablicy: HRESULT arrfunin([in] long nsize, [in, size_is(nsize)] long array[]); HRESULT arrfunout([out, in] long *nsize, [out, size_is(nsize)] long array[]); należy zauważyć, że parametr użyty w size_in może być tylko wejściowy [in] lub wejściowo-wyjściowy [in, out]. Wynika z tego, że COM będzie zawsze wiedzieć, jak dużą tablicę udostępnił klient. Serwer może zapełnić tylko część tej tablicy, stosownie ustawiając parametr nsize. Z tego względu warto rozważyć następującą modyfikację funkcji arrfunout, w której rozdzielono parametr wejściowy i wyjściowy: HRESULT arrfunout2([in] nsizein, [out, size_is(nsizein)] long array[], [out] long *nsizeout); Przekazywanie struktur jest łatwe, gdyż IDL pozwala na bezpośrednie definiowanie struktur: typedef struct Date int D; int M; int Y; ;... HRESULT structfun([in] Date birthdate); Sprawa się komplikuje, gdy elementami struktury są wskaźniki na inne struktury, które również powinny być odwzorowane w ramach marshalingu. Kompilator IDL musi dokładnie wiedzieć, na co wskazuje wskaźnik nie należy więc raczej stosować typu void*. Jeśli przekazywany jest wskaźnik na interfejs COM, dobrym pomysłem jest przekazanie w osobnym parametrze jego IID. Służy temu specjalny określnik iid_is: HRESULT intfun([in] const IID &iid, [out, iid_is(iid)] IUnknown **ppv); Oczywiście mniej więcej to samo można uzyskać przekazując typ interfejsu wprost, np.: HRESULT intfun_naive([out] IMyInterface **ppv); rozwiązanie takie zemści się jednak, gdy zamiast wskaźnika na IMyInterface zechcemy przesłać coś, co wskazuje na jakąś klasę wywiedzoną z IMyInterface. PRZYKŁAD DEFINICJI BIBLIOTEKI TYPÓW: OBJAŚNIENIA: library coclass [ uuid(3221ccff-68b2-442b-afdc-fa9c767f1fc4), version(1.0), helpstring("przykładowa biblioteka typów") ] library MyTypeLib importlib("stdole32.tlb") ; [ uuid(e843265d-b374-4d56-a980-0ec5e9188b47), helpstring("klasa komponentu") ] coclass Component [default] interface IA; interface IB; ; ; definiuje bibliotekę typów o podanym GUID (LIBID). Biblioteka może zawierać jeden lub więcej komponentów klas składników definiuje klasę składników o podanym GUID (CLSID). Klasa może udostępniać jeden lub więcej interfejsów. Jeden z nich może być domyślny, (istotne dla języków makr i VB). Opis powyższy ma charakter wstępny; w szczególności pominięto zagadnienia związane z definiowaniem dispinterfejsów (dipinterface, propget, propput, dual, oleautomation). Wyczerpujący opis języka IDL można znaleźć w MSDN; dobrym sposobem nauki IDL jest też analizowanie różnych dostępnych definicji klas.

23 TWORZENIE SKŁADNIKÓW ZEWNĄTRZPROCESOWYCH Poniższy zwięzły opis przedstawia najważniejsze kroki niezbędne dla uzyskania klienta i serwera zewnątrzprocesowego COM (serwer w pliku EXE). Tekst ten powinien być używany łącznie z instrukcją dot. tworzenia składników wewnątrzprocesowych (inproc). Ilustracją jest też kod źródłowy approach4, a także inne materiały dostępne na stronie sun.iinf.polsl.gliwice.pl/~jfrancik/lectures/com.html. 1. STWORZENIE SPECYFIKACJI IDL Ten krok przebiega tak samo, jak w przypadku składników inproc. 2. STWORZENIE APLIKACJI KLIENCKIEJ Jedyną różnicą pomiędzy aplikacją korzystającą ze składnika zewnątrzprocesowego (w stosunku do aplikacji używającej składnika inproc) jest wartość trzeciego parametru funkcji CoCreateinstance, która musi zawierać ustawiony bit CLSCTX_LOCAL_SERVER. 3. STWORZENIE MODUŁU DLL PROXY Moduł proxy jest niezbędny przy komunikacji klienta z serwerem zewnątrzprocesowym, nie wymaga jednak specjalnego kodowania. Wystarczy w tym celu: - Stworzyć projekt DLL obejmujący następujące pliki źródłowe, automatycznie generowane podczas kompilacji specyfikacji IDL: dlldata.c, abc_i.c, abc_p.c (przy założeniu, że kompilowano plik abc.idl). - Włączyć linkowanie nastepujących bibliotek (poza standardowymi): rpcndr.lib, rpcns4.lib i rpcrt4.lib. - Dodać definicję symbolu REGISTER_PROXY_DLL - Dołączyć plik def (por. przykład approach4) - Skompilować i zlinkować projekt. - Zarejestrować otrzymany plik DLL (za pomocą opcji Tools Register Control w Visual Studio lub wywołując program regsvr32). 4. STWORZENIE MODUŁU EXE SERWERA Większa część kodu źródłowego serwerów zewnątrz- i wewnątrzprocesowych jest taka sama. W szczególności punkty 1 4 w części instrukcji dotyczącej tworzenia serwerów inproc można zastosować do serwerów zewnątrzprocesowych. Punkty 5 7 tej instrukcji nie odnoszą się do serwerów w plikach EXE, w szczególności nie ma tu funkcji eksportowanych. Oto specyficzne dla tego typu serwerów czynności dodatkowe: 1. Stworzenie funkcji WinMain jak w przykładzie Approach4. Poniżej przedstawiono najważniejsze elementy: - Inicjalizacja systemu COM (CoInitialize). - Analiza linii wywołania: parametrów RegServer (rejestracja serwera), UnregServer (wyrejestrowanie serwera) i Embedding (praca tylko w trybie serwera, a nie aplikacji zwykle powoduje wyłączenie wyświetlenia okna aplikacji). [Uwaga wśród plików projektu Approach4 znajduja się pliki Registry.h i Registry.cpp z modyfikacjami niezbędnymi przy obsłudze składników zewnątrzprocesowych] - Utworzenie i rejestracja fabryk(i) klas (funkcja CoRegisterClassObject). - Wyświetlenie okna (zwykle z wyjątkiem trybu /Embedding) i petla komunikatów - Wyrejestrowanie fabryk(i) klas (CoRevokeClassObject) i deinicjalizacja COM (CoUninitialize) 2. Implementacja zarządzania usuwaniem aplikacji z pamięci. Wymaga to: - przy dekrementacji globalnych liczników (g_ccomponents i g_cserverlocks) sprawdzenia, czy aplikacja nie powinna być usunięta z pamięci: - if (g_ccomponents == 0 && g_cserverlocks == 0) PostQuitMessage(0); - Blokady usuwania aplikacji, gdy używany jest interfejs użytkownika (okno aplikacji): - InterlockedIncrement(&g_cServerLocks); wywołane tuż po otwarciu okna - Zniesienia powyższej blokady w chwili zamknięcia okna aplikacji: - case WM_CLOSE: ::InterlockedDecrement(&g_cServerLocks); w funkcji okienkowej - Dodatkowej kontroli podczas obsługi komunikatu WM_DESTROY: case WM_DESTROY: if (g_ccomponents == 0 && g_cserverlocks == 0) PostQuitMessage(0); 3. Zarejestrowanie serwera poprzez wywołanie go z parametrem /RegServer. opracowanie: Jarosław Francik

24 Interfejs IDispatch, dispinterfejsy i automatyzacja Jarosław Francik Interface Idispatch : IUnknown HRESULT GetTypeInfoCount([out] UINT RPC_FAR *pctinfo); HRESULT GetTypeInfo( [in] UINT itinfo, [in] LCID lcid, [out] ITypeInfo RPC_FAR * RPC_FAR *pptinfo); HRESULT GetIDsOfNames( [in] REFIID riid, [in] LPOLESTR RPC_FAR *rgsznames, [in] UINT cnames, [in] LCID lcid, [out, size_is(cnames)] DISPID RPC_FAR *rgdispid); HRESULT Invoke( [in] DISPID dispidmember, [in] REFIID riid, [in] LCID lcid, [in] WORD wflags, [in] DISPPARAMS RPC_FAR *pdispparams, [out] VARIANT RPC_FAR *pvarresult, [out] EXCEPINFO RPC_FAR *pexcepinfo, [out] UINT RPC_FAR *puargerr); ; interfejs IDispatch (IDL) Dispinterface Dispinterface Klient IDispatch QueryInterface Składnik COM Klient IDispatch QueryInterface Składnik COM AddRef Release GetTypeInfoCount dispinterface "fun1" 1 "fun2" 2 AddRef Release GetTypeInfoCount dispinterface "fun1" 1 "fun2" 2 GetTypeInfo GetIDsOfNames Invoke "fun3" 3 1 fun1 2 fun2 GetTypeInfo GetIDsOfNames Invoke "fun3" 3 pvtbl fun1 fun2 3 fun3 fun3 dual interface IDispatch Klient QueryInterface AddRef Release GetTypeInfoCount GetTypeInfo GetIDsOfNames Invoke fun1 fun2 fun3 Składnik COM dispinterface "fun1" 1 "fun2" 2 "fun3" 3 Parametry wywołania Invoke dispidmember dispid wywoływanej funkcji riid zarezerwowany, ma być IID_NULL lcid użyj GetUserDefaultLCID() wflags rodzaj funkcji: DISPATCH_METHOD, DISPATCH_PROPERTYGET, DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF pdispparams tablica parametrów wywołania tagdispparams pvarresult wynik funkcji (wskaźnik na wariant) pexcepinfo, puargerr sytuacje wyjątkowe 1

25 DISPPARAMS i Warianty struct tagdispparams VARIANTARG *rgvarg; /*... */ ; struct tagvariant /*... */ VARTYPE vt; /*... */ stałe VT_* union LONG lval; VT_I4 BYTE bval; VT_UI1 SHORT ival; VT_I2 /*... */ BSTR bstrval; VT_BYREF VT_BSTR Ciekawe funkcje: SysAllocString VariantChangeType wchar_t progid[] = L"COMLecture.Approach5.1"; CLSID clsid; CLSIDFromProgID(progid, &clsid); IDispatch *pidispatch = NULL; HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pidispatch); DISPID dispid; OLECHAR *name = L"fa"; hr = pidispatch->getidsofnames(iid_null, &name, 1, GetUserDefaultLCID(), &dispid); VARIANTARG varg; VariantInit(&varg); varg.vt = VT_EMPTY; DISPPARAMS param; param.cargs = 0; param.rgvarg = &varg; param.cnamedargs = 0; param.cargs = NULL; hr = pidispatch->invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &param, NULL, NULL, NULL); Klient dla dispinterface Visual C++ i MFC: IA ia; ia.createdispatch("comlecture.approach5.1 ) ia.fa(); Visual Basic: Dim x As Object CreateObject("COMLecture.Approach5.1 ) x.fa Klienci dla dispinterface 2

26 / Kalkulator (prosty) - wersja agregowalna import "unknwn.idl"; Interface ICalc [ object, uuid(892753ed-d14e-4d2f-b e0c01f5f3), helpstring("kalkulator (prosty), wersja agregowalna"), pointer_default(unique) ] interface ICalc : IUnknown HRESULT digit([in] int n); HRESULT comma(); HRESULT sign(); HRESULT op([in] int n); HRESULT eq(); HRESULT c(); HRESULT ce(); [propget, id(1), helpstring("wyświetlacz")] HRESULT display([out, retval] double *pval); [propput, id(1), helpstring("wyświetlacz")] HRESULT display([in] double newval); ; Biblioteka typów + clsid składników [ uuid(7fb7b bd-4360e0147dd8), version(1.0), helpstring("kalkulator (prosty), wersja agregowalna, bibl.typów") ] library CalcAggrTypeLib importlib("stdole32.tlb") ; [ uuid(4d3b9d9b-8dcc-4443-bac8-1dcae ), helpstring("kalkulator (prosty), wersja agregowalna") ] coclass CalcSimple [default] interface ICalc; ; ; Serwer prostego kalkulatora - wersja agregowalna Copyright (c) 2001 by Jarosław Francik #include "stdafx.h" #include "calc2.h" plik automatycznie utworzony przez MIDL #include "calc2_i.c" plik automatycznie utworzony przez MIDL #include <iostream.h> #include "registry.h" pomocnicze narzędzia do rejestru systemowego... Zmienne globalne static HMODULE g_hmodule = NULL ; static long g_ccomponents = 0 ; static long g_cserverlocks = 0 ; uchwyt modułu DLL Licznik aktywnych składników Licznik dla LockServer Dane do rejestru systemowego const char g_szprogid[] = "Calc.SimpleAggr.2"; const char g_szfriendlyname[] = "Prosty kalkulator COM - wersja agregowalna"; const char g_szverindprogid[] = "Calc.SimpleAggr"; Interfejs INondelegatingUnknown interface INondelegatingUnknown virtual HRESULT stdcall NondelegatingQueryInterface(const IID&, void**) = 0 ; virtual ULONG stdcall NondelegatingAddRef() = 0 ; virtual ULONG stdcall NondelegatingRelease() = 0 ; ; Klasa składnika class CCalc : public ICalc, INondelegatingUnknown public: Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu INondelegatingUnknown virtual HRESULT _stdcall NondelegatingQueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall NondelegatingAddRef(); virtual ULONG _stdcall NondelegatingRelease(); Implementacja interfejsu ICalc virtual HRESULT stdcall digit(int n); virtual HRESULT stdcall comma(); virtual HRESULT stdcall sign(); virtual HRESULT stdcall op(int n); virtual HRESULT stdcall eq(); virtual HRESULT stdcall c(); virtual HRESULT stdcall ce(); virtual HRESULT stdcall get_display(double RPC_FAR *pval); virtual HRESULT stdcall put_display(double newval); Implementacja wewnętrzna double m_display, m_reg; wyświetlacz i drugi rejestr int m_op; kod operacji; 0=nic, 1-4 = + - * / bool m_bappenddisp; tryb dodawania do wyświetlacza; public: CCalc(IUnknown *punknownouter) : m_nref(1), m_display(0.0), m_reg(0.0), m_op(0), m_bappenddisp(false) InterlockedIncrement(&g_cComponents); if (punknownouter) m_punknownouter = punknownouter; zostaliśmy zagregowani! else m_punknownouter = (IUnknown*)(INondelegatingUnknown*)this; ~CCalc() InterlockedDecrement(&g_cComponents); private: long m_nref; IUnknown *m_punknownouter; obiekt do którego delegujemy odwołania ;

27 Implementacja interfejsu ICalc HRESULT stdcall CCalc::digit(int n) if (!m_bappenddisp) m_display = n; else m_display = m_display * 10 + n; m_bappenddisp = true; HRESULT stdcall CCalc::comma() return E_NOTIMPL; HRESULT stdcall CCalc::sign() m_display = -m_display; HRESULT stdcall CCalc::op(int n) eq(); m_op = n; HRESULT stdcall CCalc::eq() switch (m_op) case 1: m_display = m_reg + m_display; break; case 2: m_display = m_reg - m_display; break; case 3: m_display = m_reg * m_display; break; case 4: m_display = m_reg / m_display; break; m_reg = m_display; m_bappenddisp = false; HRESULT stdcall CCalc::c() m_reg = m_display = m_op = 0; m_bappenddisp = false; HRESULT stdcall CCalc::ce() m_display = 0; m_bappenddisp = false; HRESULT stdcall CCalc::get_display(double RPC_FAR *pval) *pval = m_display; HRESULT stdcall CCalc::put_display(double newval) m_display = newval; Implementacja interfejsu IUnknown HRESULT _stdcall CCalc::QueryInterface(REFIID iid, void **ppv) return m_punknownouter->queryinterface(iid, ppv); ULONG _stdcall CCalc::AddRef() return m_punknownouter->addref(); ULONG _stdcall CCalc::Release() return m_punknownouter->release(); Implementacja interfejsu INondelegatingUnknown HRESULT _stdcall CCalc::NondelegatingQueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (INondelegatingUnknown*)this; else if (iid == IID_ICalc) *ppv = (ICalc*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG _stdcall CCalc::NondelegatingAddRef() return InterlockedIncrement(&m_nRef); ULONG _stdcall CCalc::NondelegatingRelease() if (InterlockedDecrement(&m_nRef) == 0) delete this; return 0; return m_nref;

28 Class Factory class CFactory : public IClassFactory standardowa deklaracja interfejsu IClassFactory ; HRESULT stdcall CFactory::QueryInterface(const IID& iid, void** ppv) standardowa implementacja ULONG stdcall CFactory::AddRef() standardowa implementacja ULONG stdcall CFactory::Release() standardowa implementacja HRESULT stdcall CFactory::CreateInstance(IUnknown* punknownouter, const IID& iid, void** ppv) if (punknownouter!= NULL && iid!= IID_IUnknown) return CLASS_E_NOAGGREGATION; Utworzenie składnika CCalc* pcalc = new CCalc(pUnknownOuter); if (!pcalc) return E_OUTOFMEMORY; Utworzenie żądanego interfejsu HRESULT hr = pcalc->nondelegatingqueryinterface(iid, ppv); pcalc->nondelegatingrelease(); return hr; HRESULT stdcall CFactory::LockServer(BOOL block) standardowa implementacja Funkcje eksportowane! standardowa implementacja / Kalkulator naukowy (z wykorzystaniem agregacji) import "unknwn.idl"; Interface ICalcScientific [ object, uuid(22e6b303-cefe-4f65-9bed-8623af83903e), helpstring("kalkulator naukowy"), pointer_default(unique) ] interface ICalcScientific : IUnknown HRESULT sqroot(); ; Biblioteka typów + clsid składników [ uuid(f3b7ad02-3d70-46e d479b95e4089), version(1.0), helpstring("kalkulator naukowy, biblioteka typów") ] library CalcSciTypeLib importlib("stdole32.tlb") ; [ uuid(ba e2-42ce-b a6388e), helpstring("kalkulator naukowy - komponent zagregowany") ] coclass CalcScientific [default] interface ICalcScientific; interface ICalc; ; ; Serwer kalkulatora naukowego (z pierwiastkowaniem) Moduł agreguje składnik Calc2 - prosty kalkulator Copyright (c) 2001 by Jarosław Francik #include "stdafx.h" #include "calcsci.h" plik automatycznie utworzony przez MIDL #include "calcsci_i.c" plik automatycznie utworzony przez MIDL #include <iostream.h> #include "registry.h" pomocnicze narzędzia do rejestru systemowego... #include <math.h> #include "..\\calc2\\calc2.h" #include "..\\calc2\\calc2_i.c" Zmienne globalne jak w poprzednim przykładzie...

29 Klasa składnika class CCalcScientific : public ICalcScientific public: Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu ICalcScientific virtual HRESULT stdcall sqroot(); Funkcja inicjalizująca obiekt wewnętrzny (wywoływana przez fabrykę klas) HRESULT Init() return CoCreateInstance(CLSID_CalcSimple, (IUnknown*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_punknowninner); public: IUnknown *m_punknowninner; CCalcScientific() : m_nref(1) InterlockedIncrement(&g_cComponents); ~CCalcScientific() InterlockedDecrement(&g_cComponents); private: long m_nref; ; Implementacja interfejsu ICalcScientific HRESULT stdcall CCalcScientific::sqroot() ICalc *pcalc = NULL; HRESULT hr = m_punknowninner->queryinterface(iid_icalc, (void**)&pcalc); if (SUCCEEDED(hr)) double ddisp; pcalc->get_display(&ddisp); ddisp = sqrt(ddisp); pcalc->put_display(ddisp); return hr; Implementacja interfejsu IUnknown HRESULT _stdcall CCalcScientific::QueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (ICalcScientific*)this; else if (iid == IID_ICalcScientific) *ppv = (ICalcScientific*)this; else if (iid == IID_ICalc) return m_punknowninner->queryinterface(iid, ppv); else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG _stdcall CCalcScientific::AddRef() ULONG _stdcall CCalcScientific::Release() standardowe implementacje Class Factory standardowa implementacja fabryki klas (jak w pierwszym przykładzie) zmiany dotyczą tylko poniższego: HRESULT stdcall CFactory::CreateInstance(IUnknown* punknownouter, const IID& iid, void** ppv) if (punknownouter!= NULL) return CLASS_E_NOAGGREGATION; Utworzenie składnika CCalcScientific* pcalcscientific = new CCalcScientific; if (!pcalcscientific) return E_OUTOFMEMORY; Utworzenie wewnętrznego składnika HRESULT hr = pcalcscientific->init(); if (!SUCCEEDED(hr)) return CLASS_E_NOAGGREGATION; Utworzenie żądanego interfejsu hr = pcalcscientific->queryinterface(iid, ppv); pcalcscientific->release(); return hr; Funkcje eksportowane! standardowa implementacja

30 / Kalkulator (prosty) wersja z punktami połączeń import "unknwn.idl"; Interface ICalc [ object, uuid(14169cfc-8cc3-45ec-8c46-d080c8de6d39), helpstring("kalkulator (prosty), wersja z punktami połączenia"), pointer_default(unique) ] interface ICalc : IUnknown HRESULT digit([in] int n); HRESULT comma(); HRESULT sign(); HRESULT op([in] int n); HRESULT eq(); HRESULT c(); HRESULT ce(); [propget, id(1), helpstring("wyświetlacz")] HRESULT display([out, retval] double *pval); [propput, id(1), helpstring("wyświetlacz")] HRESULT display([in] double newval); ; Interfejs wychodzący [ object, uuid(a1284ed8-990e a-26da646245c8), helpstring("kalkulator - Interfejs wychodzący"), pointer_default(unique) ] interface IOutgoingCalc : IUnknown HRESULT changed([in] double val); HRESULT errorb([in] BSTR msg); ; Biblioteka typów + clsid składników [ uuid(af b a d21340d47), version(1.0), helpstring("kalkulator (prosty), wersja z punktami połączenia, biblioteka typów") ] library CalcAggrTypeLib importlib("stdole32.tlb") ; [ uuid(0d49456b-4a4b-423c b7299a), helpstring("kalkulator (prosty), wersja z punktami połączenia") ] coclass CalcSimple [default] interface ICalc; [source] interface IOutgoingCalc; ; ; Serwer prostego kalkulatora - wersja z punktami połączenia Copyright (c) 2001 by Jarosław Francik #include "stdafx.h" #include "calccp.h" #include "calccp_i.c" #include <iostream.h> #include "registry.h" #include <ocidl.h> plik automatycznie utworzony przez MIDL plik automatycznie utworzony przez MIDL pomocnicze narzędzia do rejestru systemowego... IConnectionPoint, IConnectionPointContainer Zmienne globalne static HMODULE g_hmodule = NULL ; static long g_ccomponents = 0 ; static long g_cserverlocks = 0 ; uchwyt modułu DLL Licznik aktywnych składników Licznik dla LockServer Dane do rejestru systemowego const char g_szprogid[] = "Calc.SimpleCP.2"; const char g_szfriendlyname[] = "Prosty kalkulator - wersja z CP ; const char g_szverindprogid[] = "Calc.SimpleCP"; Wskaźnik do interfejsu ujścia IOutgoingCalc *g_poutgoingcalc; Interfejs INondelegatingUnknown jak w pierwszym przykładzie Klasa składnika class CCalc : public ICalc, INondelegatingUnknown, IConnectionPoint, IConnectionPointContainer public: Implementacja interfejsu IUnknown virtual HRESULT _stdcall QueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); Implementacja interfejsu INondelegatingUnknown virtual HRESULT _stdcall NondelegatingQueryInterface(REFIID iid, void **ppv); virtual ULONG _stdcall NondelegatingAddRef(); virtual ULONG _stdcall NondelegatingRelease();

31 ; Implementacja interfejsu IConnectionPoint virtual HRESULT _stdcall GetConnectionInterface(IID RPC_FAR *piid); virtual HRESULT _stdcall GetConnectionPointContainer(IConnectionPointContainer RPC_FAR * RPC_FAR *ppcpc); virtual HRESULT _stdcall Advise(IUnknown RPC_FAR *punksink, DWORD RPC_FAR *pdwcookie); virtual HRESULT _stdcall Unadvise(DWORD dwcookie); virtual HRESULT _stdcall EnumConnections(IEnumConnections RPC_FAR * RPC_FAR *ppenum); Implementacja interfejsu IConnectionPointContainer virtual HRESULT _stdcall EnumConnectionPoints(IEnumConnectionPoints RPC_FAR * RPC_FAR *ppenum); virtual HRESULT _stdcall FindConnectionPoint(REFIID riid, IConnectionPoint RPC_FAR * RPC_FAR *ppcp); dalej jak w pierwszym przykładzie... Implementacja interfejsu Icalc jak w pierwszym przykładzie Implementacja interfejsu IUnknown jak w pierwszym przykładzie Implementacja interfejsu INondelegatingUnknown HRESULT _stdcall CCalc::NondelegatingQueryInterface(REFIID iid, void **ppv) if (iid == IID_IUnknown) *ppv = (INondelegatingUnknown*)this; else if (iid == IID_ICalc) *ppv = (ICalc*)this; else if (iid == IID_IConnectionPoint) *ppv = (IConnectionPoint*)this; else if (iid == IID_IConnectionPointContainer) *ppv = (IConnectionPointContainer*)this; else ppv = NULL; return E_NOINTERFACE; ((IUnknown*)(*ppv))->AddRef(); ULONG _stdcall CCalc::NondelegatingAddRef() standardowa implementacja ULONG _stdcall CCalc::NondelegatingRelease() standardowa implementacja Implementacja interfejsu IConnectionPoint HRESULT _stdcall CCalc::GetConnectionInterface(IID RPC_FAR *piid) return E_NOTIMPL; HRESULT _stdcall CCalc::GetConnectionPointContainer(IConnectionPointContainer RPC_FAR * RPC_FAR *ppcpc) return E_NOTIMPL; HRESULT _stdcall CCalc::Advise(IUnknown RPC_FAR *punksink, DWORD RPC_FAR *pdwcookie) Wartość cookie jest nieistotna przy jednym połączeniu *pdwcookie = 1; oto wskaźnik do interfejsu ujścia return punksink->queryinterface(iid_ioutgoingcalc, (void**)&g_poutgoingcalc); HRESULT _stdcall CCalc::Unadvise(DWORD dwcookie) g_poutgoingcalc->release(); g_poutgoingcalc = NULL; HRESULT _stdcall CCalc::EnumConnections(IEnumConnections RPC_FAR * RPC_FAR *ppenum) return E_NOTIMPL; Implementacja interfejsu IConnectionPointContainer HRESULT _stdcall CCalc::EnumConnectionPoints(IEnumConnectionPoints RPC_FAR * RPC_FAR *ppenum) return E_NOTIMPL; HRESULT _stdcall CCalc::FindConnectionPoint(REFIID riid, IConnectionPoint RPC_FAR * RPC_FAR *ppcp) if (riid == IID_IOutgoingCalc) return QueryInterface(IID_IConnectionPoint, (void**)ppcp); return E_NOINTERFACE; Class Factory I funkcje eksportowane standardowa implementacja fabryki klas (jak w pierwszym przykładzie)

32 Zawieranie i agregacja Zawieranie (Containment) Powtórne użycie (reuse) Dziedziczenie implementacji Przesłanianie tożsamości obiektów Zawieranie = Containment Agregacja = Aggregation ICalcScientific ICalc CalcScientific ICalc CalcSimple IUnknown IUnknown Agregacja (Aggregation) Punkty połączeń IUnknown SERWER ICalcScientific CalcScientific INondelegatingUnknown IUnknown IConnectionPoint ICalc CalcSimple KLIENT ujście (sink) IConnectionPoint Punkty połączeń interface IConnectionPoint : IUnknown Wymień dostępne punkty połączenia HRESULT GetConnectionInterface([out] IID RPC_FAR *piid); Podaj pojemnik punktów połączenia HRESULT GetConnectionPointContainer( [out] IConnectionPointContainer *ppcpc); Przyjmij wskaźnik do mojego ujścia HRESULT Advise( [in] IUnknown *punksink, [out] DWORD *pdwcookie); Nie wywołuj już mojego ujścia HRESULT Unadvise([in] DWORD dwcookie); Wymień połączenia HRESULT EnumConnections([out] IEnumConnections *ppenum); ; Punkty połączeń IConnectionPointContainer : public IUnknown Wymień dostępne punkty połączenia HRESULT EnumConnectionPoints([out] IEnumConnectionPoints *ppenum); ; Znajdź wskazany punkt połączenia HRESULT FindConnectionPoint([in] REFIID riid, [out] IConnectionPoint *ppcp); 1

33 Wielowątkowość w Windows Wielowątkowość w COM Marek Mittmann Grudzień 2002 Wątek (ang.( thread) ) to sekwencja wykonywana przez proces, każdy proces ma do wykonania jeden lub więcej wątków Tam, gdzie wątki korzystają ze współdzielonych danych, konieczna jest synchronizacja Do synchronizacji wykorzystujemy: zdarzenia, sekcje krytyczne, semafory i wzajemne wykluczanie obiektów (mutex) Przedziały Typy przedziałów Przedział (ang.( apartment) ) to kolekcja obiektów wraz z ich kontekstami Każdy obiekt należy do dokładnie jednego przedziału Przedziały określają zestaw zasad dla danej grupy obiektów, wymaganych do poprawnej pracy w środowisku wielowątkowym Jednowątkowe (STA) Mają po jednym wątku, proces może mieć wiele STA Synchronizowane przy pomocy kolejki komunikatów Wielowątkowe (MTA) Mają wiele wątków, proces może mieć tylko jeden MTA Brak synchronizacji Neutralne (NA) Proces może mieć jeden NA Proces Proces Przedziały a wątki STA STA STA MTA MTA Przedziały jednowątkowe Każdy STA ma tylko jeden wątek, w pojedynczym procesie może istnieć wiele STA Wszystkie komponenty nie obsługujące modelu wielowątkowego działają w głównym STA Wątek deklaruje obsługę modelu STA przez wywołanie CoInitializeEx z drugim parametrm równym COINIT_APARTMENTTHREAD

34 Przedziały jednowątkowe c.d. Przedziały wielowątkowe Wywołania metod w STA są automatycznie synchronizowane i dysponowane przy użyciu kolejek komunikatów Każdy komponent zewnątrzprocesowy, który obsługuje model STA, musi zawierać pętlę komunikatów Komponent wykonywalny może blokować wywołania metod w STA za pomocą filtrów komunikatów (interfejs IMessageFilter) W pojedynczym procesie może istnieć tylko jeden MTA, który z kolei może zawierać wiele wątków Wywołania metod w MTA nie są automatycznie synchronizowane Wątek deklaruje obsługę modelu STA przez wywołanie CoInitializeEx z drugim parametrm = COINIT_MULTITHREAD Przedziały neutralne W pojedynczym procesie może istnieć tylko jeden NA Nie ma stałych wątków, obiekty z NA są zawsze wykonywane przez wątek wywołujący Brak wbudowanej synchronizacji Przedziały neutralne są obsługiwane tylko przez komponenty wewnątrzprocesowe Przedziały a komponenty wewnątrzprocesowe Komponenty wewnątrzprocesowe nie wywołują CoInitializeEx,, obsługiwany model wielowątkowości deklarują za pomocą wpisu w rejestrze (klucz CLSID\InprocServer32 InprocServer32). Dopuszczalne wartości to: Apartment STA Neutral NA Free MTA Both obsługuje STA, NA i MTA brak komponent jednowątkowy Przypisywanie do przedziałów Współdziałanie przedziałów Typ przedziału twórcy Model wielowątkowości komponentu Nieokreślony Apartment Free Both Neutral Proces Główny STA główny STA główny STA MTA główny STA NA Obiekt Pośrednik Obiekt Lekki pośrednik STA główny STA STA wywołującego MTA STA wywołującego NA STA MTA MTA główny STA macierzysty STA MTA MTA NA Obiekt Lekki pośrednik Obiekt NA (wątek STA) główny STA STA wywołującego MTA NA NA STA NA NA (wątek MTA) główny STA macierzysty STA MTA NA NA

35 Współdziałanie przedziałów Typ przedziału twórcy Główny STA Model wielowątkowości komponentu Nieokreślony Apartment Free Both Neutral bezpośredni dostęp bezpośredni dostęp dostęp przez pośrednika bezpośred ni dostęp dostęp przez lekkiego pośrednika Przekazywanie interfejsów pomiędzy przedziałami STA1 IMyInterface* pmyinterface; CoCreateInstance(CLSID_MyCOMClass, NULL, CLSCTX_LOCAL_SERVER, IID_IMyInterface, (void**)&pmyinterface); void MyThread(IStream* pscream) Utwórz STA2 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); STA MTA NA (wątek STA) dostęp przez pośrednika dostęp przez pośrednika dostęp przez pośrednika bezpośredni dostęp dostęp przez pośrednika dostęp przez lekkiego pośrednika dostęp przez pośrednika bezpośredni dostęp dostęp przez pośrednika bezpośred ni dostęp bezpośred ni dostęp bezpośred ni dostęp dostęp przez lekkiego pośrednika dostęp przez lekkiego pośrednika bezpośredni dostęp IStream* pstream; CoMarshalInterThreadInterfaceInStream( IID_IMyInterface, pmyinterface, &pstream); DWORD threadid; CreateThread(0, 0, (LPTHREAD_START_ROUTINE) MyThread, (void*)pstream, 0, &threadid); IMyInterface* pmyinterface; CoGetInterfaceAndReleaseStream( pstream, IID_IMyInterface, (void**) &pmyinterface);... pmyinterface->release(); NA (wątek MTA) dostęp przez pośrednika dostęp przez pośrednika dostęp przez lekkiego pośrednika bezpośred ni dostęp bezpośredni dostęp... pmyinterface->release(); CoUninitialize(); Podsumowanie Podsumowanie c.d. Każdy STA może mieć tylko jeden wątek Komponenty wykorzystujace wątki STA muszą pobierać i dysponować komunikaty okna Przekazywanie wskaźników interfejsów pomiedzy wątkami z różnych przedziałów powinno odbywać się za pośrednictwem szeregowania Każdy wątek korzystający z COM powinien wywołać CoInitializeEx Każdy obiekt jest związany tylko z jednym, ale przedział może zawierać wiele obiektów Główny STA jest tworzony przez wątek, który pierwszy wywoła CoInitializeEx z COINIT_APARTMENTTHREAD Proces może mieć wiele STA, ale tylko jeden MTA i jeden NA Dla obiektów wewnątrzprocesowych należy zdefiniować w rejestrze ThreadingModel

36 Kategorie komponentów Programowanie składnikowe w modelu COM Jarosław Francik maj 2002 Kategorie komponentów Cel: usprawnienie wyszukiwania klas komponentów Pozycje rejestru systemowego: W HKEY_CLASSES_ROOT: Component Categories zestawienie kategorii (CATID) dla poszczególnych klas: Implemented Categories Required categories Kategorie komponentów Domyślne klasy można je tworzyć nie znając CLSID, a tylko CATID! Emulacja klas: klucz TreatAs funkcja CoTreatAsClass Component Categories Manager interface ICatRegister interface ICatInformation 1

37 Programowanie składnikowe w modelu COM Jarosław Francik maj 2002 Trwałość (Persistency) PODSTAWOWE INTERFEJSY TRWAŁOŚCI: IPersist IPersistStream IPersistStreamInit IPersistStorage IPersistFile IPersistPropertyBag PODSTAWOWY INTERFEJS IPERSIST interface IPersist : IUnknown HRESULT GetClassID([out] CLSID *pclsid); ; OBSŁUGA STRUMIENI interface IPersistStreamInit : IPersist HRESULT IsDirty(); HRESULT Load([in, unique] IStream *pstr); HRESULT Save([in, unique] IStream *pstr, [in] BOOL fcleardirty); HRESULT GetSizeMax([out] ULARGE_INTEGER *psize); HRESULT InitNew(); ; ZAPIS TRWAŁEGO OBIEKTU pobieramy clsid klasy CLSID clsid; hr = ppersistent->getclassid(&clsid); zapisujemy clsid (standardowa funkcja) hr = WriteClassStm(pStream, clsid) zapisujemy dane obiektu hr = ppersistent->save(pstream, TRUE); interface ISequentialStream : IUnknown HRESULT Read([out, size_is(cb), length_is(*pread)] void *p, [in] ULONG cb, [out] ULONG *pread); HRESULT Write( [out, size_is(cb)] void *p, [in] ULONG cb, [out] ULONG *pwritten); ; ODCZYT TRWAŁEGO OBIEKTU pobieramy CLSID CLSID clsid; hr = ReadClassStm(pStream, &clsid); tworzymy nowe wystąpienie obiektu IPersistStream *ppersistent; hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IPersistStream, (void**)ppersistent); PRACA Z ZESTAWAMI WŁAŚCIWOŚCI Wciągamy dane obiektu ppersistent->load(pstream); SPRYTNE FUNKCJE STANDARDOWE hr = OleSaveToStream(pPersistent, pstream); hr = OleLoadFromStream(pPersistent, pstream); interface IPersistPropertyBag : IPersist HRESULT IsDirty(); HRESULT Load([in] IPropertyBag *ppropbag, [in] IErrorLog *perrorlog); HRESULT Save([in] IPropertyBag *ppropbag, [in] BOOL fcleardirty, [in[ BOOL bsaveallprops); HRESULT GetSizeMax([out] ULARGE_INTEGER *psize); HRESULT InitNew(); ; interface IPropertyBag : IUnknown HRESULT Read([in] LPCOLESTR ppropname, [in, out] VARIANT *pvar, [in] IErrorLog *perrorlog); ; HRESULT Write([in] LPCOLESTR ppropname, [in] VARIANT *pvar); opracowanie: Jarosław Francik

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

//////////////////////////////////////////////////////////// // Kalkulator (prosty) - wersja agregowalna import unknwn.idl; / Kalkulator (prosty) - wersja agregowalna import "unknwn.idl"; Interface ICalc uuid(892753ed-d14e-4d2f-b812-041e0c01f5f3), helpstring("kalkulator (prosty), wersja agregowalna"), interface ICalc : IUnknown

Bardziej szczegółowo

// LISTING #2 DRUGIE PODEJŚCIE

// LISTING #2 DRUGIE PODEJŚCIE OD KLASY C++ DO SERWERA COM: PROGRAMY PRZYKŁADOWE DO WYKŁADU PROGRAMOWANIE SKŁADNIKOWE W MODELU COM OPRACOWANIE: JAROSŁAW FRANCIK // LISTING #1 PIERWSZE PODEJŚCIE // LISTING #2 DRUGIE PODEJŚCIE #include

Bardziej szczegółowo

Obiekty w plikach wykonywalnych, marshaling

Obiekty w plikach wykonywalnych, marshaling Obiekty w plikach wykonywalnych, marshaling Komponent w pliku exe Odczyt IClassFactory komponencie umieszczonym w pliku dll ładowanym w przestrzeń adresową klienta następuje poprzez wywołanie eksportowanej

Bardziej szczegółowo

Technologie COM i ActiveX COM - Component Object Model

Technologie COM i ActiveX COM - Component Object Model Technologie COM i COM - Component Object Model Jarosław Francik COM - Common Object Model Program - monolit Program składnikowy Składnik A Składnik B Składnik C Składnik D Składnik E Architektura składnikowa

Bardziej szczegółowo

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

Droga do DCOM DCOM (1996) Windows clipboard (1987) OLE 1 DDE (1992) OLE 2 (1993) COM (1995) Distributed computing (1980s) COM jako standard Droga do DCOM Windows clipboard (1987) OLE 1 DDE (1992) OLE 2 (1993) COM (1995) Distributed computing (1980s) Open Software Foundation Distributed Computing Environment Remote Procedure

Bardziej szczegółowo

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

Agregacja. Wykorzystanie innego komponentu bez użycia agregacji. Simple calculator. Extended calculator Agregacja Agregacja Agregacja jest to wykorzystywanie przez komponent nadrzędny innego komponentu w taki sposób, że udostępnia jego interfejs jako własny. Aby komponent mógł być użyty jako agregat, metody

Bardziej szczegółowo

Microsoft Interface Definition Language

Microsoft Interface Definition Language Microsoft Interface Definition Language IDL IDL (Interface Definition Language) kompilowany jest przez MIDL.exe: Tworzy pliki nagłówkowe klas abstrakcyjnych dla zdefiniowanych w pliku *.idl interfejsów

Bardziej szczegółowo

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

Henryk Budzisz. materiały przygotowane w ramach projektu ZPORR nr POKL.04.01.01-00-449/08-00 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

Bardziej szczegółowo

Zdarzenia (events, connection points)

Zdarzenia (events, connection points) (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ń.

Bardziej szczegółowo

1.1. Kontrolki ActiveX. Kontrolki ActiveX. Technologia ActiveX. Technologia ActiveX. Technologia ActiveX. Technologia ActiveX.

1.1. Kontrolki ActiveX. Kontrolki ActiveX. Technologia ActiveX. Technologia ActiveX. Technologia ActiveX. Technologia ActiveX. 1 Katedra Optoelektroniki i Systemów Elektronicznych 2 Kontrolki Oprogramowanie Systemów Elektronicznych Zagadnienia: Temat wykładu Kontrolki 1. Technologia 2. 3. Rejestrowanie kontrolek 4. Projektowanie

Bardziej szczegółowo

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.

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. Zgłaszanie błędów HRESULT Każda metoda interfejsu COM zwraca informację o błędzie w postaci typu HRESULT (long int). Struktura reprezentacji bitowej HRESULT podzielona jest na 4 sekcje: 1 bit błędu 4 bity

Bardziej szczegółowo

Component Object Model laboratorium 2013 K.M. Ocetkiewicz, T. Goluch

Component Object Model laboratorium 2013 K.M. Ocetkiewicz, T. Goluch Component Model laboratorium 2013 K.M. Ocetkiewicz, T. Goluch 1. Wstęp COM jest standardem tworzenia komponentów w systemie Windows. Standard ten jest binarny dotyczy skompilowanego kodu (a nie języka

Bardziej szczegółowo

IFiZR Laboratorium 5 Info

IFiZR Laboratorium 5 Info IFiZR Laboratorium 5 Info File->New->Project->Windows Application (DevC++) Kurs WinAPI: http://cpp0x.pl/kursy/kurs-winapi-c++/167 #include #include #include #include

Bardziej szczegółowo

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

Interfejs IUnknown. Każdy obiekt COM musi implementować interfejs IUnknown, który zawiera trzy metody: Plan wykładu 1. Technologia COM (DCOM) wprowadzenie, korzystanie z obiektu COM, program klienta, schemat programu serwera. 2. Porównanie DCOM, CORBA i RMI. Wprowadzenie Opracowana przez Microsoft technologia

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Wykład 2 Marcin Młotkowski 4 marca 2015 Plan wykładu 1 2 3 4 5 Marcin Młotkowski Programowanie obiektowe 2 / 47 Krótki opis C Obiektowy, z kontrolą typów; automatyczne odśmiecanie;

Bardziej szczegółowo

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

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość 1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość 2. Poprawna definicja wskażnika b to: a) float *a, **b = &a; b) float

Bardziej szczegółowo

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

Programowanie 2. Język C++. Wykład 3. 3.1 Programowanie zorientowane obiektowo... 1 3.2 Unie... 2 3.3 Struktury... 3 3.4 Klasy... 4 3.5 Elementy klasy... 5 3.6 Dostęp do elementów klasy... 7 3.7 Wskaźnik this... 10 3.1 Programowanie zorientowane

Bardziej szczegółowo

Wykład 8: klasy cz. 4

Wykład 8: klasy cz. 4 Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD

Bardziej szczegółowo

TEMAT : KLASY DZIEDZICZENIE

TEMAT : KLASY DZIEDZICZENIE TEMAT : KLASY DZIEDZICZENIE Wprowadzenie do dziedziczenia w języku C++ Język C++ możliwa tworzenie nowej klasy (nazywanej klasą pochodną) w oparciu o pewną wcześniej zdefiniowaną klasę (nazywaną klasą

Bardziej szczegółowo

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

Programowanie składnikowe. Programowanie składnikowe w modelu COM. COM - Component Object Model. wprowadzenie. Programowanie składnikowe Programowanie składnikowe w modelu COM wprowadzenie Jarosław Francik COM - Component Object Model Programowanie składnikowe Programowanie składnikowe 1 Program - monolit 1 Program składnikowy Składnik

Bardziej szczegółowo

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch INFORMATOR TECHNICZNY WONDERWARE Informator Techniczny nr 60 04-12-2002 Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch Wstęp PoniŜsza dokumentacja oparta na przykładach stworzonych

Bardziej szczegółowo

Język ludzki kod maszynowy

Język ludzki kod maszynowy Język ludzki kod maszynowy poziom wysoki Język ludzki (mowa) Język programowania wysokiego poziomu Jeśli liczba punktów jest większa niż 50, test zostaje zaliczony; w przeciwnym razie testu nie zalicza

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Wykład 2 28 lutego 2019 Plan wykładu 1 2 3 4 5 Plan wykładu 1 2 3 4 5 Krótki opis C Obiektowy, z kontrolą typów; automatyczne odśmiecanie; standardy ISO i ECMA; podobny składniowo do C++; Język C Krótka

Bardziej szczegółowo

Component Object Model laboratorium 2017 K.M. Ocetkiewicz, T. Goluch

Component Object Model laboratorium 2017 K.M. Ocetkiewicz, T. Goluch Component Model laboratorium 2017 K.M. Ocetkiewicz, T. Goluch 1. Wstęp COM jest standardem tworzenia komponentów w systemie Windows. Standard ten jest binarny dotyczy skompilowanego kodu (a nie języka

Bardziej szczegółowo

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost; Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze

Bardziej szczegółowo

JAVA W SUPER EXPRESOWEJ PIGUŁCE

JAVA W SUPER EXPRESOWEJ PIGUŁCE JAVA W SUPER EXPRESOWEJ PIGUŁCE Obiekt Obiekty programowe to zbiór własności i zachowań (zmiennych i metod). Podobnie jak w świecie rzeczywistym obiekty posiadają swój stan i zachowanie. Komunikat Wszystkie

Bardziej szczegółowo

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

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016 Wykład 1 3 marca 2016 Słowa kluczowe języka Java abstract, break, case, catch, class, const, continue, default, do, else, enum, extends, final, finally, for, goto, if, implements, import, instanceof, interface,

Bardziej szczegółowo

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Zaawansowane programowanie w języku C++ Programowanie obiektowe Zaawansowane programowanie w języku C++ Programowanie obiektowe Prezentacja jest współfinansowana przez Unię Europejską w ramach Europejskiego Funduszu Społecznego w projekcie pt. Innowacyjna dydaktyka

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Wykład 2: Wstęp do języka Java 3/4/2013 S.Deniziak: Programowanie obiektowe - Java 1 Cechy języka Java Wszystko jest obiektem Nie ma zmiennych globalnych Nie ma funkcji globalnych

Bardziej szczegółowo

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

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi EGZAMIN PIERWSZY (25 CZERWCA 2013) JĘZYK C++ poprawiam ocenę pozytywną z egzaminu 0 (zakreśl poniżej x) 1. Wśród poniższych wskaż poprawną formę definicji

Bardziej szczegółowo

Tworzenie projektu asemblerowego dla środowiska Visual Studio 2008.

Tworzenie projektu asemblerowego dla środowiska Visual Studio 2008. Dwiczenie 5. TEMAT: CEL: Tworzenie projektu asemblerowego dla środowiska Visual Studio 2008. Celem dwiczenia jest poznanie możliwości VS 2008 w zakresie tworzenia i uruchamiania aplikacji z kodem mieszanym

Bardziej szczegółowo

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

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02 METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE Wykład 02 NAJPROSTSZY PROGRAM /* (Prawie) najprostszy przykład programu w C */ /*==================*/ /* Między tymi znaczkami można pisać, co się

Bardziej szczegółowo

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

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie? 1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie? a) konstruktor b) referencje c) destruktor d) typy 2. Które z poniższych wyrażeń są poprawne dla klasy o nazwie

Bardziej szczegółowo

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

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p. Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni Wykład 3 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Abstrakcja funkcyjna Struktury Klasy hermetyzacja

Bardziej szczegółowo

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

Techniki programowania INP001002Wl rok akademicki 2017/18 semestr letni. Wykład 4. Karol Tarnowski A-1 p. Techniki programowania INP001002Wl rok akademicki 2017/18 semestr letni Wykład 4 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Dziedziczenie Przestrzenie nazw Na podstawie: A.

Bardziej szczegółowo

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

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np Klasy Klasa jest nowym typem danych zdefiniowanym przez użytkownika Wartości takiego typu nazywamy obiektami Najprostsza klasa jest po prostu strukturą, np struct Zespolona { Klasy jako struktury z operacjami

Bardziej szczegółowo

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

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

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

Projektowanie obiektowe. Roman Simiński  Wzorce projektowe Wybrane wzorce strukturalne Projektowanie obiektowe Roman Simiński roman.siminski@us.edu.pl www.siminskionline.pl Wzorce projektowe Wybrane wzorce strukturalne Fasada Facade Pattern 2 Wzorzec Fasada Facade Pattern koncepcja 3 Wzorzec

Bardziej szczegółowo

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

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016 Wykład 2 17 marca 2016 Dziedziczenie Klasy bazowe i potomne Dziedziczenie jest łatwym sposobem rozwijania oprogramowania. Majac klasę bazowa możemy ja uszczegółowić (dodać nowe pola i metody) nie przepisujac

Bardziej szczegółowo

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy : Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy : class nazwa_klasy prywatne dane i funkcje public: publiczne dane i funkcje lista_obiektów;

Bardziej szczegółowo

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

Podstawy programowania skrót z wykładów: Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace

Bardziej szczegółowo

1 Atrybuty i metody klasowe

1 Atrybuty i metody klasowe 1 Atrybuty i metody klasowe Składowe klasowe (statyczne) Każdy obiekt klasy posiada własny zestaw atrybutów. Metody używają atrybutów odpowiedniego obiektu. Czasem potrzeba atrybutów wspólnych dla wszystkich

Bardziej szczegółowo

Wykład 5 Okna MDI i SDI, dziedziczenie

Wykład 5 Okna MDI i SDI, dziedziczenie Wykład 5 Okna MDI i SDI, dziedziczenie Autor: Zofia Kruczkiewicz Zagadnienia 1. Aplikacja wielookienkowa. Zakładanie projektu typu CLR Windows Forms 1.1. Aplikacja typu MDI 1.2. Aplikacja typu SDI 2. Dziedziczenie

Bardziej szczegółowo

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

Pola i metody statyczne. Klasy zawierające pola i metody statyczne Instrukcja laboratoryjna nr 1 Programowanie w języku C 2 (C++ poziom zaawansowany) Pola i metody statyczne. Klasy zawierające pola i metody statyczne dr inż. Kaczmarek Tomasz mgr inż. Lasota Maciej dr

Bardziej szczegółowo

Programowanie w Internecie. Java

Programowanie w Internecie. Java Programowanie w Internecie Java Autor: dr inż. Zofia Kruczkiewicz Literatura: L. Lemay, R. Cadenhead P. Naughton Krzysztof Barteczko Boone Barry Java 2 dla każdego Podręcznik Języka Programowania Java

Bardziej szczegółowo

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C #import "Fraction.h" #import @implementation Fraction -(Fraction*) initwithnumerator: (int) n denominator: (int) d { self = [super init]; } if ( self ) { [self setnumerator: n anddenominator:

Bardziej szczegółowo

Część 4 życie programu

Część 4 życie programu 1. Struktura programu c++ Ogólna struktura programu w C++ składa się z kilku części: część 1 część 2 część 3 część 4 #include int main(int argc, char *argv[]) /* instrukcje funkcji main */ Część

Bardziej szczegółowo

Structured storage, Monikers, Running Object Table

Structured storage, Monikers, Running Object Table Structured storage, Monikers, Running Object Table Structured storage Structured storage jest sposobem zorganizowanego zapisywania danych w pliku. Struktura danych ma postać drzewa i obiektów danych podobną

Bardziej szczegółowo

Instrukcja laboratoryjna cz.3

Instrukcja laboratoryjna cz.3 Języki programowania na platformie.net cz.2 2015/16 Instrukcja laboratoryjna cz.3 Język C++/CLI Prowadzący: Tomasz Goluch Wersja: 2.0 I. Utworzenie projektu C++/CLI z interfejsem graficznym WPF 1 Cel:

Bardziej szczegółowo

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU Inicjalizacja agregatowa zmiennej tablicowej int a[5] = 1,2,3,4,5 INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU Struktury są również agregatami, dlatego: struct X double f; char c; X x1 = 1, 2.2, 'c' Ale

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe IV. Interfejsy i klasy wewnętrzne Małgorzata Prolejko OBI JA16Z03 Plan Właściwości interfejsów. Interfejsy a klasy abstrakcyjne. Klonowanie obiektów. Klasy wewnętrzne. Dostęp do

Bardziej szczegółowo

Szablony klas, zastosowanie szablonów w programach

Szablony klas, zastosowanie szablonów w programach Szablony klas, zastosowanie szablonów w programach 1. Szablony klas i funkcji 2. Szablon klasy obsługującej uniwersalną tablicę wskaźników 3. Zastosowanie metody zwracającej przez return referencję do

Bardziej szczegółowo

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1) MAS dr. Inż. Mariusz Trzaska Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1) Zagadnienia o Podstawy o Kontrolowanie sterowania o Klasy o Interfejsy o Obsługa błędów o Pojemniki o System

Bardziej szczegółowo

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

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton Dzisiejszy wykład Wzorce projektowe Visitor Client-Server Factory Singleton 1 Wzorzec projektowy Wzorzec nazwana generalizacja opisująca elementy i relacje rozwiązania powszechnie występującego problemu

Bardziej szczegółowo

Aplikacje RMI https://docs.oracle.com/javase/tutorial/rmi/overview.html

Aplikacje RMI https://docs.oracle.com/javase/tutorial/rmi/overview.html Aplikacje RMI https://docs.oracle.com/javase/tutorial/rmi/overview.html Dr inż. Zofia Kruczkiewicz wykład 4 Programowanie aplikacji internetowych, wykład 4 1 1. Zadania aplikacji rozproszonych obiektów

Bardziej szczegółowo

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

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne Przeciążenie funkcji polega na użyciu funkcji z tą samą nazwą, które mają różne listy argumentów(różne typy, różna ilość lub to i inne).

Bardziej szczegółowo

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

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium: Zakres laboratorium: definiowanie struktur terminologia obiektowa definiowanie klas funkcje składowe klas programy złożone z wielu plików zadania laboratoryjne Laboratorium nr 12 Temat: Struktury, klasy.

Bardziej szczegółowo

Wykład 4: Klasy i Metody

Wykład 4: Klasy i Metody Wykład 4: Klasy i Metody Klasa Podstawa języka. Każde pojęcie które chcemy opisać w języku musi być zawarte w definicji klasy. Klasa definiuje nowy typ danych, których wartościami są obiekty: klasa to

Bardziej szczegółowo

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

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami. UML a kod w C++ i Javie Projektowanie oprogramowania Dokumentowanie oprogramowania Diagramy przypadków użycia Przewoznik Zarzadzanie pojazdami Optymalizacja Uzytkownik Wydawanie opinii Zarzadzanie uzytkownikami

Bardziej szczegółowo

Projektowanie i programowanie aplikacji biznesowych. Wykład 2

Projektowanie i programowanie aplikacji biznesowych. Wykład 2 Projektowanie i programowanie aplikacji biznesowych Wykład 2 Kontrolki w Windows API Aby korzystać z kontrolek należy dołączyć plik nagłówkowy o nazwie commctrl.h oraz bibliotekę o nazwie libcomctl32.a.

Bardziej szczegółowo

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje Zbudujemy klasę Definicję klasy zapiszmy w pliku tstring.h #ifndef TSTRING_H #define TSTRING_H #include // w pliku nagłówkowym NIE // otwieramy przestrzeni std // interfejs private: // implementacja

Bardziej szczegółowo

Podstawy Programowania Obiektowego

Podstawy Programowania Obiektowego Podstawy Programowania Obiektowego Wprowadzenie do programowania obiektowego. Pojęcie struktury i klasy. Spotkanie 03 Dr inż. Dariusz JĘDRZEJCZYK Tematyka wykładu Idea programowania obiektowego Definicja

Bardziej szczegółowo

Zarządzanie pamięcią

Zarządzanie pamięcią System COM, aby mógł śledzić zmiany w alokacji pamięcią podczas wywołań, obsługuje pamięć niezależnie od Runtime Library (RT) C++ i korzysta ze sterty bieżącego procesu. Do obsługi pamięci COM, zdefiniowany

Bardziej szczegółowo

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

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h] 1. Typy. Java jest językiem programowania z silnym systemem kontroli typów. To oznacza, że każda zmienna, atrybut czy parametr ma zadeklarowany typ. Kompilator wylicza typy wszystkich wyrażeń w programie

Bardziej szczegółowo

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta 16.09.2006. Strona 1 z 26. Powrót. Full Screen. Zamknij.

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta 16.09.2006. Strona 1 z 26. Powrót. Full Screen. Zamknij. Programowanie Sobera Jolanta 16.09.2006 Strona 1 z 26 1 Wprowadzenie do programowania 4 2 Pierwsza aplikacja 5 3 Typy danych 6 4 Operatory 9 Strona 2 z 26 5 Instrukcje sterujące 12 6 Podprogramy 15 7 Tablice

Bardziej szczegółowo

Materiały do zajęć VII

Materiały do zajęć VII Spis treści I. Klasy Materiały do zajęć VII II. III. Konstruktor Właściwości i indeksatory Klasy Programowanie obiektowe wiadomości wstępne Paradygmat programowania obiektowego Abstrakcja Hermetyzacja

Bardziej szczegółowo

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

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object Java: kilka brakujących szczegółów i uniwersalna nadklasa Object Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak PLAN WYKŁADU Konstrukcja obiektów Niszczenie obiektów i zwalnianie zasobów

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

Dokumentacja do API Javy.

Dokumentacja do API Javy. Dokumentacja do API Javy http://java.sun.com/j2se/1.5.0/docs/api/ Klasy i obiekty Klasa jest to struktura zawierająca dane (pola), oraz funkcje operujące na tych danych (metody). Klasa jest rodzajem szablonu

Bardziej szczegółowo

Praca w środowisku Visual Studio 2008, Visual C

Praca w środowisku Visual Studio 2008, Visual C Praca w środowisku Visual Studio 2008, Visual C++ 2008 mgr inż. Tomasz Jaworski tjaworski@kis.p.lodz.pl http://tjaworski.kis.p.lodz.pl/ Tworzenie aplikacji konsolowych 2 3 Tworzenie nowego projektu aplikacji

Bardziej szczegółowo

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

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static), Tworzenie obiektów Dostęp do obiektów jest realizowany przez referencje. Obiekty w języku Java są tworzone poprzez użycie słowa kluczowego new. String lan = new String( Lancuch ); Obszary pamięci w których

Bardziej szczegółowo

Programowanie obiektowe w C++ Wykład 12

Programowanie obiektowe w C++ Wykład 12 Programowanie obiektowe w C++ Wykład 12 dr Lidia Stępień Akademia im. Jana Długosza w Częstochowie L. Stępień (AJD) 1 / 22 Zakresowe pętle for double tab[5] {1.12,2.23,3.33,4.12,5.22 for(double x: tab)

Bardziej szczegółowo

Wykład 5: Klasy cz. 3

Wykład 5: Klasy cz. 3 Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu

Bardziej szczegółowo

PROE wykład 4 pozostałe operatory, forward declaration, dziedziczenie. dr inż. Jacek Naruniec

PROE wykład 4 pozostałe operatory, forward declaration, dziedziczenie. dr inż. Jacek Naruniec PROE wykład 4 pozostałe operatory, forward declaration, dziedziczenie dr inż. Jacek Naruniec Kolokwium wykładowe Pierwsze kolokwium 6 kwietnia Drugie kolokwium 1 czerwca Kolokwium poprawkowe 8 czerwca

Bardziej szczegółowo

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27 Programowanie w C++ Wykład 14 Katarzyna Grzelak 3 czerwca 2019 K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27 Na ostatnim wykładzie: Konstruktor standardowy (domyślny) to taki, który nie ma żadnych argumentów

Bardziej szczegółowo

Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do programowanie obiektowego w języku C++ Wprowadzenie do programowanie obiektowego w języku C++ Część czwarta Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści wykładu, lektura

Bardziej szczegółowo

Wstęp do Programowania 2

Wstęp do Programowania 2 Wstęp do Programowania 2 dr Bożena Woźna-Szcześniak bwozna@gmail.com Akademia im. Jana Długosza Wykład 5 W programowaniu obiektowym programista koncentruje się na obiektach. Zadaje sobie pytania typu:

Bardziej szczegółowo

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

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej. 1/8 Singleton Cel: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej. Przykład: Niekiedy ważne jest, aby tworzyć tylko jedną instancję jakiejś klasy. Globalne zmienne

Bardziej szczegółowo

Szablony funkcji i szablony klas

Szablony funkcji i szablony klas Bogdan Kreczmer bogdan.kreczmer@pwr.wroc.pl Zakład Podstaw Cybernetyki i Robotyki Instytut Informatyki, Automatyki i Robotyki Politechnika Wrocławska Kurs: Copyright c 2011 Bogdan Kreczmer Niniejszy dokument

Bardziej szczegółowo

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych. Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych. 1. Przygotowanie środowiska programistycznego. Zajęcia będą

Bardziej szczegółowo

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.) Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.) przeznaczony do programowania zarówno pod ios jak i Mac OS X bazuje na logice Objective-C bez kompatybilności

Bardziej szczegółowo

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

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27 Programowanie w C++ Wykład 12 Katarzyna Grzelak 28 maja 2018 K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27 Klasy cd K.Grzelak (Wykład 12) Programowanie w C++ 2 / 27 Klasy - powtórzenie Klasy typy definiowane

Bardziej szczegółowo

I - Microsoft Visual Studio C++

I - Microsoft Visual Studio C++ I - Microsoft Visual Studio C++ 1. Nowy projekt z Menu wybieramy File -> New -> Projekt -> Win32 Console Application w okienku Name: podajemy nazwę projektu w polu Location: wybieramy miejsce zapisu i

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Literatura: Autor: dr inŝ. Zofia Kruczkiewicz Java P. L. Krzysztof Lemay, Naughton Barteczko R. Cadenhead JAVA, Java Podręcznik 2 wykłady dla kaŝdego Języka i ćwiczenia Programowania

Bardziej szczegółowo

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania Zofia Kruczkiewicz Zakres Funkcje przetwarzające teksty (biblioteka ) - tworzenie własnych

Bardziej szczegółowo

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

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak Java język programowania obiektowego Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak 1 Język Java Język Java powstał w roku 1995 w firmie SUN Microsystems Java jest językiem: wysokiego

Bardziej szczegółowo

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami: Wskaźniki są nieodłącznym elementem języka C. W języku C++ także są przydatne i korzystanie z nich ułatwia pracę, jednak w odróżnieniu do C wiele rzeczy da się osiągnąć bez ich użycia. Poprawne operowanie

Bardziej szczegółowo

Wstęp do programowania obiektowego, wykład 7

Wstęp do programowania obiektowego, wykład 7 Wstęp do programowania obiektowego, wykład 7 Klasy i funkcje abstrakcyjne Przeciążanie funkcji Definiowanie i interpretacja złożonych typów danych w C++ Wskaźniki do funkcji 1 KLASA ABSTRAKCYJNA 2 Klasa

Bardziej szczegółowo

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej. Polimorfizm jest filarem programowania obiektowego, nie tylko jeżeli chodzi o język C++. Daje on programiście dużą elastyczność podczas pisania programu. Polimorfizm jest ściśle związany z metodami wirtualnymi.

Bardziej szczegółowo

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

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Programowanie obiektowe i zdarzeniowe

Programowanie obiektowe i zdarzeniowe Marek Tabędzki Programowanie obiektowe i zdarzeniowe 1/23 Programowanie obiektowe i zdarzeniowe wykład 6 polimorfizm Na poprzednim wykładzie: dziedziczenie jest sposobem na utworzenie nowej klasy na podstawie

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

10. Programowanie obiektowe w PHP5

10. Programowanie obiektowe w PHP5 Ogólnie definicja klasy wygląda jak w C++. Oczywiście elementy składowe klasy są zmiennymi PHP, stąd nieśmiertelne $. Warto zauważyć, że mogą one mieć wartość HHH mgr inż. Grzegorz Kraszewski TECHNOLOGIE

Bardziej szczegółowo

Klasy abstrakcyjne i interfejsy

Klasy abstrakcyjne i interfejsy Klasy abstrakcyjne i interfejsy Streszczenie Celem wykładu jest omówienie klas abstrakcyjnych i interfejsów w Javie. Czas wykładu 45 minut. Rozwiązanie w miarę standardowego zadania matematycznego (i nie

Bardziej szczegółowo

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec PROE wykład 3 klasa string, przeciążanie funkcji, operatory dr inż. Jacek Naruniec Przypomnienie z ostatnich wykładów Konstruktory/destruktory i kolejność ich wywołania w złożonej klasie. Referencja Obiekty

Bardziej szczegółowo

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Java - tablice, konstruktory, dziedziczenie i hermetyzacja Java - tablice, konstruktory, dziedziczenie i hermetyzacja Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak PLAN WYKŁADU zmienne tablicowe konstruktory klas dziedziczenie hermetyzacja

Bardziej szczegółowo

PARADYGMATY PROGRAMOWANIA Wykład 4

PARADYGMATY PROGRAMOWANIA Wykład 4 PARADYGMATY PROGRAMOWANIA Wykład 4 Metody wirtualne i polimorfizm Metoda wirualna - metoda używana w identyczny sposób w całej hierarchii klas. Wybór funkcji, którą należy wykonać po wywołaniu metody wirtualnej

Bardziej szczegółowo

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

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls ) III RPC Zdalne wywoływanie procedur (ang. Remote Procedure Calls ) 1. Koncepcja Aplikacja wywołanie procedury parametry wyniki wykonanie procedury wynik komputer klienta komputer serwera Zaletą takiego

Bardziej szczegółowo

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

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz Programowanie obiektowe Literatura: Autor: dr inŝ. Zofia Kruczkiewicz Java P. L. Lemay, Naughton R. Cadenhead Java Podręcznik 2 dla kaŝdego Języka Programowania Java Linki Krzysztof Boone oprogramowania

Bardziej szczegółowo