Czym jest biblioteka Bibliotekahttp://tldp.org/HOWTO/Program-Library-HOWTO/ jest to zbiór funkcji, które zostały wydzielone po to, aby dało się z nich korzystać w wielu programach. Ułatwia to programowanie - nie musimy np. sami tworzyć funkcji printf. Każda biblioteka posiada swoje pliki nagłówkowe, które zawierają deklaracje funkcji bibliotecznych oraz często zawarte są w nich komentarze, jak używać danej funkcji. W tej części podręcznika nauczymy się tworzyć nasze własne biblioteki.

Pliki Biblioteka składa się co najmniej z dwóch plików: jeden nagłówkowy (źródłowy, API) i jeden binarny (skompilowany) zawiera funkcje (deklaracje w nagłówkowym i definicje w binarnym) w postaci pakietu (ang. package) może dzielić się na pakiety dev i non-devstackoverflow question: linux-error-while-loading-shared-libraries-cannot-open-shared-object-file-no-s

cechy jest przeznaczona do wykonania odrębnego zadania programistycznego ma ściśle określony interfejsProgramowanie funkcyjne: Modu ze strony wazniak.mimuw.edu.pl "Moduł ma charakter czarnej skrzynki (ang. black-box approach). Na zewnątrz modułu widoczne są wyłącznie te obiekty programistyczne, które tworzą interfejs. Natomiast sposób ich implementacji, jak i ewentualne obiekty pomocnicze są ukryte wewnątrz modułu."

Zasady budowy bibliotek ( modułów) wg strony wazniak.mimuw.edu.pl:Programowanie funkcyjne: Modu ze strony wazniak.mimuw.edu.pl powiązania między modułami powinny być jak najmniejsze; jak najmniej szczegółów budowy jednego modułu miało wpływ na budowę innego modułu, każdy moduł powinien koncentrować się wokół jednej decyzji projektowej, tzw. "sekretu" modułu, przy czym nie należy łączyć nie związanych ze sobą sekretów w jednym module; zasada ta jest znana pod nazwą separation of concerns, użytkownicy modułów powinni polegać jedynie na tym, co jest określone w interfejsie i specyfikacji modułu, natomiast nie powinni polegać na żadnym konkretnym sposobie implementacji modułu, tzw. black-box approach.

typy wg architektury sposobu wykorzystania autora rozszerzenia

wg sposobu wykorzystania statyczne (ang. static library or statically-linked library)stackoverflow question : difference-between-static-and-shared-libraries windows: .lib lub .obj Unix: .a lub .o dynamiczneStatic, Shared Dynamic and Loadable Linux Libraries from yolinux biblioteka łączona dynamicznie, Unix: biblioteka współdzielona (ang. shared libraryHOWTO : shared-librariesdrepper : how to write shared library, shared object) .so, ścieżki poszukiwań plików bibliotek zapisane są w pliku /etc/ld.so.conf oraz w zmiennej środowiskowej $LD_LIBRARY_PATH. Windows: .dll biblioteki ładowane dynamicznie

wg autora standardowe - biblioteka zawierająca podstawowe funkcje, dostarczana wraz z kompilatorem lub interpreterem danego języka programowania. Nie wymagaja osobnej instalacji niestandardowe, zewnętrzne, wymagajace osobnej instalacji własne

wg rozszerzenie a - biblioteki linkowane statycznie bin - pliki binarne fw - pliki firmware : biblioteki lub sterowniki sprzętu ko - pliki dla modułów jądra o - pliki obiektowe, np. ładowalne moduły jądra so - dynamicznie linkowane biblioteki dzieloneLinux Libraries (Paths, Files, and Commands) by DevynCJohnson

Ścieżka wyszukiwania Gcc w systemie Linuks wyszukuje nagłówki #include w kilku standardowych katalogach:gcc : Search-Path Where Does GCC Look to Find its Header Files? by Joshua Davie

/usr/local/include libdir/gcc/target/version/include /usr/target/include /usr/include

Możemy to sprawdzić za pomocą przełączników przy kompilacji: gcc c.c -v -c

przykładowy wynik:

ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include search starts here: /usr/lib/gcc/x86_64-linux-gnu/4.8/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list.

Zmienna środowiskowa LD_LIBRARY_PATH zawiera ścieżki do katalogów bibliotek. Te katalogi kompilator będzie przeszukiwał w trakcie kompilacji:stackoverflow :How to add a default include path for gcc in linux? LD_LIBRARY_PATH W celu dopisania ścieżki do własnej biblioteki ustaw wartość zmiennej środowiskowej, na przykład w konsoli wpisz: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib32:/usr/lib32 gdzie /lib32 i /usr/lib32 są dopisywanymi ścieżkami do bibliotek (plików *.so). Jak widzimy w przykładzie, ścieżki oddzielamy dwukropkiem.

Sprawdzamy jakie ścieżki są przeszukiwane: Stackoverflow : GCC include directories echo | gcc -Wp,-v -x c++ - -fsyntax-only

przykładowy wynik: ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/4.8" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include search starts here: /usr/include/c++/4.8 /usr/include/x86_64-linux-gnu/c++/4.8 /usr/include/c++/4.8/backward /usr/lib/gcc/x86_64-linux-gnu/4.8/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list.

Zależności ldd ( wyszukiwanie w kodzieanalyzing-c-source-files-dependencies-in-a-program by balau82

Jak zbudowana jest biblioteka Kod źródłowy każdej biblioteki składa się z co najmniej dwóch części (oczywiście w praktyce nie istnieje górny limit): pliku nagłówkowego z deklaracjami funkcji (plik z rozszerzeniem .h) pliku źródłowego, zawierającego ciała funkcji (plik z rozszerzeniem .c)

Biblioteka po skompilowaniu składa się z dwóch plików: nagłówkowy (źródłowy) binarny (skompilowany)

Budowa pliku nagłówkowego Plik nagłówkowy zawiera interfejs programowania aplikacji ( ang. application programming interface = API)

Oto najprostszy możliwy plik nagłówkowy: #ifndef PLIK_H #define PLIK_H /* tutaj są wpisane deklaracje funkcji */ #endif Zapewne zapytasz się na co komu instrukcje #ifndef, #define oraz #endif. Otóż często się zdarza, że w programie korzystamy z plików nagłówkowych, które dołączają się wzajemnie. Oznaczałoby to, że w kodzie programu kilka razy pojawiła by się zawartość tego samego pliku nagłówkowego. Instrukcja #ifndef i #define temu zapobiega. Dzięki temu kompilator nie musi kilkakrotnie kompilować tego samego kodu.

W plikach nagłówkowych często umieszcza się też definicje typów, z których korzysta biblioteka albo np. makr.

Budowa najprostszej biblioteki Załóżmy, że nasza biblioteka będzie zawierała jedną funkcję, która wypisuje na ekran tekst "pl.Wikibooks". Utwórzmy zatem nasz plik nagłówkowy:

#ifndef WIKI_H #define WIKI_H #include void wiki (void) {printf("pl.Wikibooks\n");} #endif

Należy pamiętać, o podaniu void w liście argumentów funkcji nie przyjmujących argumentów. O ile przy definicji funkcji nie trzeba tego robić (jak to często czyniliśmy w przypadku funkcji main) o tyle w prototypie brak słówka void oznacza, że w prototypie nie ma informacji na temat tego jakie argumenty funkcja przyjmuje.

Plik nagłówkowy zapisujemy jako "wiki.h".

Ważne jest dołączenie na początku pliku nagłówkowego. Dlaczego? Plik nagłówkowy zawiera deklaracje naszych funkcji - jeśli popełniliśmy błąd i deklaracja nie zgadza się z definicją, kompilator od razu nas o tym powiadomi. Oprócz tego plik nagłówkowy może zawierać definicje istotnych typów lub makr. Napiszmy nasz program:

#include "wiki.h"

int main () { wiki(); return 0;

Zapiszmy program jako "main.c" Teraz musimy odpowiednio skompilować nasz program:

gcc main.c -o main

Uruchamiamy nasz program:

./main pl.Wikibooks

Jak widać nasza pierwsza biblioteka działa. Zmiana dostępu do funkcji i zmiennych (static i extern) Język C, w przeciwieństwie do swego młodszego krewnego - C++ nie posiada praktycznie żadnych mechanizmów ochrony kodu biblioteki przed modyfikacjami. C++ ma w swoim asortymencie m.in. sterowanie uprawnieniami różnych elementów klasy. Jednak programista, piszący program w C nie jest tak do końca bezradny. Autorzy C dali mu do ręki dwa narzędzia: extern oraz static. Pierwsze z tych słów kluczowych informuje kompilator, że dana funkcja lub zmienna istnieje, ale w innym miejscu, i zostanie dołączona do kodu programu w czasie łączenia go z biblioteką.

extern przydaje się, gdy zmienna lub funkcja jest zadeklarowana w bibliotece, ale nie jest udostępniona na zewnątrz (nie pojawia się w pliku nagłówkowym). Przykładowo:

/* biblioteka.h */ #ifndef BIBLIOTEKA_H #define BIBLIOTEKA_H extern char zmienna_dzielona[]; #endif /* biblioteka.c */ #include "biblioteka.h"

char zmienna_dzielona[] = "Zawartosc";

/* main.c */ #include #include "biblioteka.h"

int main() { printf("%s\n", zmienna_dzielona); return 0;

Gdybyśmy tu nie zastosowali extern, kompilator (nie linker) zaprotestowałby, że nie zna zmiennej zmienna_dzielona. Próba dopisania deklaracji char zmienna_dzielona[]; stworzyłaby nową zmienną i utracilibyśmy dostęp do interesującej nas zawartości.

Odwrotne działanie ma słowo kluczowe static użyte w tym kontekście (użyte wewnątrz bloku tworzy zmienną statyczną, więcej informacji w rozdziale Zmienne). Może ono odnosić się zarówno do zmiennych jak i do funkcji globalnych. Powoduje, że dana zmienna lub funkcja jest niedostępna na zewnątrz bibliotekiTak naprawdę całe "ukrycie" funkcji polega na zmianie niektórych danych w pliku z kodem binarnym danej biblioteki (pliku .o), przez co linker powoduje wygenerowanie komunikatu o błędzie w czasie łączenia biblioteki z programem.. Możemy dzięki temu ukryć np. funkcje, które używane są przez samą bibliotekę, by nie dało się ich wykorzystać przez extern.

Rozwiązywanie problemów ustal jaką bibliotekę potrzebujesz czy ta biblioteka jest zainstalowana? jeśli tak to gdzie jeśli nie to zainstaluj ścieżki gdzie jest zainstalowana biblioteka (pliki binarne i nagłówkowe) gdzie kompilator/program wyszukuje biblioteki pokaż kompilatorowi/programowi gdzie szukać bibliotekę

Przykłady biblioteka standardowa libm = biblioteka matematyczna POSIX Threads (w skrócie pthreads)= biblioteka udostępniająca jednolite API dla języka C do tworzenia i zarządzania wątkami, jest dostępna w systemach m.in. Linux, FreeBSD, Windows OpenMP ICU ( ang. Internaltional Components for Unicode) to dojrzały, szeroko stosowany zestaw bibliotek C/C++ i Java zapewniający obsługę Unicode i globalizacji dla aplikacji libffi - A Portable Foreign Function Interface Library - przenośny interfejs programowania wysokiego poziomu do różnych konwencji wywoływania ( języków programowania) libsoundio - c library, cross-platform audio input and output for real-time & consumer software biblioteki skłądające się z 1 pliku nagłówkowego (ang. Single-header-file C libraries) arkanis : single-header-file-c-libs clibs ccan = Comprehensive C Archive Network stb-style jit - API do osadzania GCC w programach i bibliotekach klib - biblioteka ogólna w C BoxFort - Piaskownica_(bezpieczeństwo_informatyczne, ang. sandboxing)fortinet: what-is-sandboxing ? debugbreak - break into the debugger programmatically dynacall nanopb to implementacja C formatu danych Google Protocol Buffers. Jest przeznaczony dla 32-bitowych mikrokontrolerów, ale nadaje się również do innych systemów wbudowanych z wąskimi ograniczeniami pamięci (<10 kB ROM, <1 kB RAM).

Wg zastosowania grafika

klib Common components of klib khash.h: generic hash table with open addressing. kbtree.h: generic search tree based on B-tree. kavl.h: generic intrusive AVL tree. ksort.h: generic sort, including introsort, merge sort, heap sort, comb sort, Knuth shuffle and the k-small algorithm. kseq.h: generic stream buffer and a FASTA/FASTQ format parser. kvec.h: generic dynamic array. klist.h: generic single-linked list and memory pool. kstring.{h,c}: basic string library.