Programowanie Zespołowe 2004/2005 Zespół VIII

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

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

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

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

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Programowanie obiektowe zastosowanie języka Java SE

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

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

Wyjątki (exceptions)

Wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

Tworzenie oprogramowania

Programowanie w systemie Linux. Jacek Lach Zakład Oprogramowania Instytut Informatyki Politechnika Śląska

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

Język C++ wykład VIII

I - Microsoft Visual Studio C++

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

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

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

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

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

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

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

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

Obsługa wyjątków. Język C++ WW12

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Przekazywanie argumentów wskaźniki

Programowanie obiektowe i C++ dla matematyków

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

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Część 4 życie programu

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Wprowadzenie do biblioteki klas C++

Programowanie proceduralne w języku C++ Podstawy

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

Java jako język programowania

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 25 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 38

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

Programowanie w języku C++

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

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

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

1 Atrybuty i metody klasowe

1 Podstawy c++ w pigułce.

ATD. Wykład 8. Programowanie (język C++) abstrakcyjny typ danych. Abstrakcyjne typy danych (ATD) Metody czysto wirtualne. Definicje i uwagi:

Projektowanie klas c.d. Projektowanie klas przykład

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

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

Plik klasy. h deklaracje klas

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

PARADYGMATY PROGRAMOWANIA Wykład 4

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

Wstęp do Programowania 2

Informatyka. Wy-08 Klasy. mgr inż. Krzysztof Kołodziejczyk

Tworzenie projektu asemblerowego dla środowiska Visual Studio 2008.

Programowanie obiektowe

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Listy powiązane zorientowane obiektowo

Podstawy języka skryptowego Lua

Zaawansowane programowanie w języku C++ Programowanie obiektowe

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

Programowanie - wykład 4

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Multimedia JAVA. Historia

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

Zmienne i struktury dynamiczne

Programowanie komputerowe. Zajęcia 1

WPROWADZENIE. Programowanie Obiektowe Mateusz Cicheński

Wstęp do programowania

Zasady programowania Dokumentacja

Przeciążenie (przeładowanie nazw) funkcji

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

Pytania sprawdzające wiedzę z programowania C++

Wykład 8: klasy cz. 4

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

Programowanie Obiektowe i C++

Instrukcja laboratoryjna cz.3

Języki programowania - podstawy

C++ - [1-3] Debugowanie w Qt Creator

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

2.4 Dziedziczenie. 2.4 Dziedziczenie Przykłady programowania w C - kurs podstawowy

Programowanie obiektowe i C++ dla matematyków

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

ECLIPSE wnioski z dwóch pierwszych laboratoriów

Wstęp do Programowania, laboratorium 02

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

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

Paostwowa Wyższa Szkoła Zawodowa w Płocku Dariusz Wardowski

4. Wyrzuć wyjątek jeśli zmienna ist nie istnieje bloki: try, catch i wyrzucanie wyjątku

Pracownia specjalistyczna. Materiały przygotowali: mgr inż. Wojciech Frohmberg, mgr inż. Michał Kierzynka

Laboratorium 1. I. Zainstaluj program Eclipse (wersja C/C++ w odpowiednim systemie operacyjnym

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

Transkrypt:

Toruń 2005 Programowanie Zespołowe 2004/2005 Zespół VIII Portowalne biblioteki dynamiczne Autor: Lessnau Adam WPROWADZENIE Biblioteka to plik zawierający skompilowany kod i dane, które mogą zostać dołączone do programów. Biblioteki pozwalają na większą elastyczność kodu programów, przyspieszają procesy rekompilacji oraz ułatwiają wprowadzanie poprawek. Generalnie wyróżniamy trzy rodzaje bibliotek: statyczne (static library) współdzielone (shared library) dynamicznie ładowane (dynamically loaded DL) Warto zauważyć, że niektórzy ludzie używają terminu biblioteka łączona dynamicznie (DLL) do określenia biblioteki dzielonej, inni natomiast mianem biblioteki DLL opisują dowolną bibliotekę, którą można wykorzystać jako bibliotekę DL (ładowaną dynamicznie). Są też tacy, dla których termin DLL jest równoznaczny z obydwoma określeniami. BIBLIOTEKI STATYCZNE Biblioteki statyczne są po prostu zbiorami najzwyklejszych plików obiektowych. Tradycyjnie, pod systemami unix'owymi, używa się w ich przypadku rozszerzenia '.a'. Zbiory te tworzone są przy użyciu programu ar (archiver). Obecnie nie są tak często używane jak dawniej. Związane jest to z zaletami, jakie posiadają (opisane poniżej) biblioteki dzielone. Niemniej jednak biblioteki statyczne wciąż są czasami tworzone. Biblioteki statyczne umożliwiają użytkownikom łączenie (konsolidowanie) z programami bez konieczności rekompilowania ich kodu, co stanowi dużą oszczędność czasu kompilacji. Biblioteki statyczne są często użyteczne dla twórców, którzy pragną by programiści konsolidowali swoje programy z ich bibliotekami, ale równocześnie nie chcą udostępniać kodu źródłowego. Teoretycznie, kod ze statycznej biblioteki, która została skonsolidowana do pliku wykonywalnego, powinien wykonywać się trochę szybciej (ok. 1-5%) niż kod wykorzystujący biblioteki

dzielone lub dynamicznie ładowane, jednak w praktyce w związku z innymi czynnikami wpływającymi na działanie aplikacji rzadko da się to potwierdzić. BIBLIOTEKI WSPÓŁDZIELONE Biblioteki dzielone są bibliotekami ładowanymi przez programy w czasie ich uruchamiania. Gdy biblioteka dzielona zostanie prawidłowo zainstalowana w systemie, wszystkie nowo uruchamiane programy automatycznie z niej korzystają. W rzeczywistości obsługa bibliotek dzielonych w nowoczesnych systemach, jak np. Linux, jest jeszcze bardziej elastyczna i zaawansowana gdyż pozwala na: aktualizacje bibliotek przy zachowaniu obsługi programów, które chcą korzystać ze starszych, niezgodnych wstecz wersji tych bibliotek; zastępowanie specyficznych bibliotek, czy też nawet specyficznych funkcji w bibliotece podczas wykonywania określonych programów; dokonywanie tego wszystkiego, podczas gdy w systemie działają programy korzystające z zainstalowanych bibliotek. W Linuksie system nazewnictwa shared libraries jest dość skomplikowany. Istnieją bowiem trzy różne nazwy: tzw. 'soname', 'real name' i 'linker name'. W dużym uproszczeniu można powiedzieć, iż nazwa pliku powinna mieć przedrostek 'lib' i rozszerzenie '.so'. Zainteresowancych odsyłam pod adres: http://www.tldp.org/howto/program-library-howto/shared-libraries.html. BIBLIOTEKI DL Biblioteki ładowane dynamicznie (DL) są bibliotekami ładowanymi po uruchomieniu programu. Ponieważ możliwe jest wstrzymanie procesu załadowania takich bibliotek do momentu, gdy będą one potrzebne, są one szczególnie użyteczne przy tworzeniu różnego rodzaju wtyczek i modułów. Biblioteki ładowane dynamicznie w systemie Linux nie wyróżniają się z punktu widzenia swojego formatu. Zbudowane są one tak jak omawiane uprzednio standardowe biblioteki dzielone, czy też pliki obiektowe. Podstawową różnicą jest to, że nie są one ładowane automatycznie podczas uruchamiania bądź konsolidowania programu. Zamiast tego, do operowania na funkcjach biblioteki, dostępu do jej obiektów, obsługi błędów oraz jej otwierania i zamykania, wykorzystywany jest interfejs API. Linux generalnie używa takiego samego interfejsu API jak system Solaris - nazywać go będziemy interfejsem dlopen(). Jednak nie wszystkie platformy korzystają z tego mechanizmu. Na przykład HP-UX posługuje się metodą shl_load(), BeOS load_add_on(), a platforma Windows używa systemu bibliotek DLL z całkowicie innym interfejsem LoadLibrary(). Jeżeli chcielibyśmy zbudować aplikację portowalną na wiele systemów, do ładowania i wykorzystywania bibliotek warto rozważyć zastosowanie pakietu 'GNU libtool'.

Pakiet 'GNU libtool' jest zbiorem skryptów wspomagających operacje na bibliotekach. Dostarcza on przenaszalnego interfejsu do takich operacji jak tworzenie plików obiektowych, linkowania bibliotek (statycznych i dzielonych), konsolidowania i debugowania programów wykonywalnych oraz instalowanie zarówno programów jak i bibliotek. LibTool zawiera również bibliotekę libltdl, która to jest przenośnym wraperem służącym do dynamicznego ładowania programów. Poniżej omówię przykładowe wykorzystanie biblioteki 'libltdl' do ładowania plugin'ów. W celu poznania pozostałych możliwości 'GNU libtool' odsyłam do manuala owego pakietu. BIBLIOTEKA LIBLTDL W celu użycia 'libltdl' w swoich programach należy dołączyć nagłówek `ltdl.h': #include <ltdl.h> W poniższych przykładzie korzystam z następujących typów zdefiniowanych w `ltdl.h': Typ: lt_ptr lt_ptr jest zwykłym wskaźnikiem. Typ: lt_dlhandle lt_dlhandle jest uchwytem do modułów. Każdy moduł otwarty 'lt_dlopened' jest skojarzony z lt_dlhandle. Oraz z następujących funkcji zdefiniwanych w `ltdl.h': Funkcja: int lt_dlinit (void) Inicjuje 'libltdl'. Musi zostać wywołana przed użyciem 'libldtl' i może być wywoływana kilka razy. Jeśli zakończy się sukcesem to zwraca 0, w przeciwnym razie zwraca numer błędu. Funkcja: int lt_dlexit (void) Zamyka 'libltdl' wraz z wszystkimi otwartymi modułami. Podobnie jak 'lt_dlinit' może być wywoływana kilka razy i zwraca 0 w przypadku sukcesu. W przeciwnym razie zwraca numer błędu. Funkcja: lt_dlhandle lt_dlopen (const char *filename) Otwiera moduł z pliku o nazwie 'filename' i zwraca uchwyt na niego. lt_dlopen jest zdolna otwierać dynamiczne moduły, przeładowalne statyczne moduły, sam program oraz natywne biblioteki dynamiczne. Wywoływana kilkukrotnie na tym samym module zwraca za każdym razem ten sam uchwyt. Jeśli libltdl nie może znaleźć modułu w katalogu z programem funkcja przeszukuje dodatkowo pozostałe katalogi z modułami (ścieżki poszukiwań) w następującej kolejności: 1. ścieżki zdefiniowane przez użytkownika - owe ścieżki mogą być zmieniane przez funkcje lt_dlsetsearchpath, lt_dladdsearchdir and lt_dlinsertsearchdir. 2. ścieżki znajdujące się w zmiennej środowiskowej LTDL_LIBRARY_PATH 3. systemowe katalogi z bibliotekami - np. pod Linuksem umieszczone są w zmiennej LD_LIBRARY_PATH Funkcja: lt_dlhandle lt_dlopenext (const char *filename)

Działa identycznie jak 'lt_dlopen' z tą jednak różnicą, że jeśli nie znajdzie pliku o nazwie 'filename' to próbuje znaleźć plik o takiej samej trzonowej nazwie ale innym rozszerzeniu (np.: '.la', '.so', '.sl'). Funkcja: int lt_dlclose (lt_dlhandle handle) Zmnejsza wskaźnik referencji do modułu. Jeśli wskaźnik osiągnie zero oraz żaden inny moduł nie jest zależny od powyższego modułu, wtedy moduł zostaje zwolniony. Zwraca 0 w przypadku sukcesu. Funkcja: lt_ptr lt_dlsym (lt_dlhandle handle, const char *name) Zwraca adres funkcji o nazwie 'name' w module 'handle'. Jeśli dana funkcja nie istnieje w module zwracane jest NULL. Funkcja: const char * lt_dlerror (void) Zwraca napis opisujący ostatni błąd spowodowany przez funkcje 'libltdl'. Zwraca NULL w przypadku gdy nie wystąpił żaden błąd od momentu inicjalizacji lub od ostatniego wywołania owej funkcji. Funkcja: int lt_dlsetsearchpath (const char *search_path) Nadpisuje istniejącą ścieżkę poszukiwań użytkownika wartością 'search_path', która to musi być listą bezwzględnych ścieżek oddzielonych przecinkiem. Zwraca 0 w przypadku sukcesu. Funkcja: int lt_dlforeachfile (const char *search_path, int (*func) (const char *filename, lt_ptr data), lt_ptr data) Dla każdego modułu znajdującego się w katalogu 'search_path' wywołuje funcję 'func' przekazując jej nazwę modułu oraz dane 'data'. W przypadku, gdy funkcja 'func' zwróci wartość niezerową funkcja 'lt_dlforeachfile' kończy działanie. Jeśli 'search_path' wynosi NULL to funckja przeszukuje wszystkie standardowe lokacje zgodnie z kolejności opisaną powyżej. 'lt_dlforeachfile' zwraca wartość zwróconą przez ostatnio wywałaną funkcję 'func'. PRZYKŁAD W C++ Główny program wygląda następując: #include <iostream> #include <vector> #include <ltdl.h> #include <dirent.h> #include "plugin.h" using namespace std; /* * klada Plugin - odpowiada za każdy załadowany moduł */ class Plugin public: Plugin (DefaultPlugin* defaultplugin, DestroyPlugin destroyplugin) plugin = defaultplugin; destroy = destroyplugin; ~Plugin ()

destroy (plugin); plugin = NULL; ; DefaultPlugin* plugin; DestroyPlugin destroy; /* * klada Application - zarządza modułami, tzn. umożliwia ich załadowanie, zwolnienie oraz wywoływanie funkcji w nich zawartych */ class Application vector<plugin*> plugins; vector<lt_dlhandle> handle; friend int loadplugintmp (const char *filename, lt_ptr data); int loadplugin (const char *filename); public: void init (); void loadplugins (const char* folder); void run (); void close (); ; // pomocnicza funkcja, wraper dla metody load_plugin int loadplugintmp (const char *filename, lt_ptr data) ((Application*)data)->loadPlugin (filename); // inicjuje bibliotekę libltdl void Application::init () lt_dlinit (); // laduje plugin o nazwie filename do pamieci int Application::loadPlugin (const char *filename) lt_dlhandle handletmp; CreatePlugin create; DestroyPlugin destroy; DefaultPlugin *plugin; try handletmp = lt_dlopenext (filename); if (handletmp == NULL) throw int(1); handle.push_back (handletmp);

create = (CreatePlugin) lt_dlsym (handletmp, "create"); destroy = (DestroyPlugin) lt_dlsym (handletmp, "destroy"); if ((create == NULL) (destroy == NULL)) throw int(2); plugins.push_back (new Plugin (create (), destroy)); cout << " - OK" << endl; catch (int i) switch (i) case 1: cout << " - FAIL (it's not plugin)" << endl; break; case 2: cout << " - FAIL (function 'create' does't exist)" << endl; break; default: throw; cout << "\t" << lt_dlerror () << endl; catch (...) cout << " - FAIL" << endl; ; return 0; // dla kazdego modulu w katalogu folder wywołuje funkcje loadplugin void Application::loadPlugins (const char* folder) lt_dlforeachfile (folder, loadplugintmp, this); // dla kazdego moduly wykonuje funkcje talk void Application::run () cout << endl << endl << "Zaczynamy gadac : " << endl; for (int i = 0; i < plugins.size(); i++) plugins[i]->plugin->talk (); cout << endl << endl; // zwalnia wszystkie moduly i zamyka ltdl void Application::close () for (int i = 0; i < plugins.size(); i++) delete plugins[i]; plugins.clear (); lt_dlexit ();

Application app; // glowne funkcja programu int main () app.init (); app.loadplugins ("./plugins"); app.run (); app.close (); return 0; Oprócz niego należy stworzyć również pluginy. Każdy plugin oparty jest na pewnym szablonie. W naszym przykładzie szablon wygląda następująco: #ifndef PLUGIN_H #define PLUGIN_H #include <iostream> using namespace std; class DefaultPlugin public: ~DefaultPlugin () cerr << "DefaultPlugin was deleted." << endl; ; virtual void talk () cout << "Wiem, ale nie powiam." << endl; typedef DefaultPlugin* (*CreatePlugin) (); typedef void (*DestroyPlugin) (DefaultPlugin*); #endif Stwórzmy jeszcze dwa pluginy (pluing_1 oraz plugin_2). Oba są prawie identyczne, dlategoteż zamieszcze kod źródłowy tylko jednego z nich. #include <iostream> #include "plugin.h" using namespace std; class Plugin1 : public DefaultPlugin public:

~Plugin1 () cerr << "Plugin1 was deleted." << endl; ; void talk (); void Plugin1::talk () cout << "Hehe, to ja pierwszy plugin!!!" << endl; extern "C" DefaultPlugin* create () return new Plugin1; extern "C" void destroy (Plugin1 *plugin) delete plugin; Plik Makefile potrzebny do skompilowowania powyższych źródeł wygląda następująco: CC=g++ #LDFLAGS=-lmy obj=plugin_1.o plugin_2.o dll=plugin_1.dll plugin_2.dll so=plugin_1.so plugin_2.so ROOT_FOLDER=../ PLUGINS_FOLDER=plugins/ linux: $(so) $(CC) main.cc -o $(ROOT_FOLDER)main -lltdl strip $(ROOT_FOLDER)main windows: $(dll) $(CC) main.cc -o $(ROOT_FOLDER)main -lltdl strip $(ROOT_FOLDER)main.exe %.o : %.cc $(CC) -fpic -c $< -o $@ %.so : %.o $(CC) -fpic -shared -o $(ROOT_FOLDER)$(PLUGINS_FOLDER)$@ $< strip $(ROOT_FOLDER)$(PLUGINS_FOLDER)$@ %.dll : %.o dlltool --export-all --output-def $<.def $< dllwrap --driver-name g++ --def $<.def -o $(ROOT_FOLDER)$(PLUGINS_FOLDER)$@ $< strip $(ROOT_FOLDER)$(PLUGINS_FOLDER)$@ clean: rm -f $(obj) *.def

Dla leniwych dołączam jeszcze plik z wszystkimi źródłami potrzebymi do stworzenia powyższego przykładu. BIBLIOGRAFIA Manual do GNU libtool - http://www.gnu.org/software/libtool/manual.html HowTo na temat bibliotek - http://www.tldp.org/howto/program-library-howto/