Biblioteki statyczne i dynamiczne (DLL)


1
Biblioteki statyczne i dynamiczne
Wprowadzenie
W trakcie pisania programu sięgamy zwykle do wielu typowych funkcji, jak np. sin
czy cos, nie zastanawiając się w jaki sposób zostaną one obliczone. Poza funkcjami
matematycznymi, w programowaniu korzysta się z procedur wprowadzania i wyprowadzania
danych, procedur operacujących na plikach, komunikacji między procesami i wielu innych.
Wszystkie te podprogramy (procedury) zgromadzone są w specjalnych plikach zwanych
bibliotekami. Każda biblioteka zawiera zestaw tematycznie związanych ze sobą
podprogramów, np, biblioteka podprogramów graficznych, matematycznych, itd. Można więc
powiedzieć, że biblioteka stanowi zbiór gotowych, przetestowanych i udokumentowanych
podprogramów (procedur), które każdy programista może wykorzystać w swoich programach.
Najcześciej podprogramy biblioteczne przechowywane są w postaci programów
półskompilowanych, co bardzo ułatwia ich dołączanie i przyśpiesza porces translacji
programu. Programy biblioteczne w postaci, zródłowej, np. zakodowane w języku Pascal,
spotyka się znacznie rzadziej.
Dołączanie podprogramów bibliotecznych do programu wykonuje się dwoma
sposobami. Pierwszy z nich polega na włączeniu podprogramów bibliotecznych do programu
już w etapie linkowania programu. Wówczas wytworzony plik wynikowy (z rozszerzenim
.EXE) zawiera nie tylko przetłumaczone instrukcje napisane przez programistę, ale także
potrzebne podprogramy biblioteczne.
Dołączane w ten sposób biblioteki określa się jako biblioteki statyczne. Istnieje też
drugi sposób dołączania, w którym podprogramy biblioteczne ładowane są do pamięci
dopiero w chwili uruchomienia programu (a nawet pózniej, gdy dany podprogram jest
potrzebny do obliczeń). W takim przypadku mówimy o bibliotekach dynamicznych.
Zarówno biblioteki statyczne jak i dynamiczne mogą być samodzielne tworzone przez
programistów, i są dostępne w wielu systemach operacyjnych, w tym w systemie MS
Windows i w systemie Linux.
Biblioteki statyczne
Do tworzenia bibliotek statycznych używane są programy nazywane czasami
bibliotekarzami. Należy do nich m.in. program TLIB firmy Borland  w typowych
przypadkach wywołanie tego programu ma postać:
TLIB plik_biblioteczny [/C] polecenia, listfile
gdzie:
plik_bibliotecznynazwa pliku tworzonej lub aktualizowanej biblioteki (z rozszerzeniem .LIB);
listfile nazwa pliku, w którym zostanie umieszczony spis zawartości biblioteki;
(parametr opcjonalny)
polecenia lista operacji do wykonania, podana w postaci symbolu operacji i modułu
biorącego udział w operacji:
2
+ dodanie wskazanego modułu do biblioteki,
- usunięcie wskazanego modułu z biblioteki,
* skopiowanie wskazanego podprogramu do pliku
(i usunięcie go z biblioteki)
-+ zastąpienie wskazanego modułu przez inny;
-* extract modulename and remove it
/C włączenie tej opcji powoduje, że te same symbole zapisane małymi i
wielkimi literami nie będą utożsamiane (ang. case sensitive);
W celu utworzenia biblioteki statycznej należy napisać odpowiednie podprogramy
(nazywane też procedurami lub funkcjami), poddać je kompilacji, a następnie połączyć je
razem tworząc bibliotekę statyczną. Przypuśćmy, że po kompilacji (zob. ćw. 4) uzyskaliśmy
pliki pola.obj i obwody.obj. Posługując się programem TLIB możemy teraz utworzyć
bibliotekę statyczną:
tlib geometr.lib +pola.obj +obwody.obj, spis.lst
W rezultacie powstanie biblioteka GEOMETR.LIB  zestawienie zawartości tej biblioteki
zostało wprowadzone do pliku SPIS.LST.
Wytworzoną bibliotekę można teraz używać wielokrotnie w różnych programach,
dopisując tylko jej nazwę jako parametr linkowania, np.
tlink32 c0x32.obj + glowny.obj, wynik.exe, , import32.lib + cw32.lib + geometr.lib;
Biblioteki dynamiczne w środowisku oprogramowania firmy Borland
Biblioteki dynamiczne są podobne do omawianych wyżej bibliotek statycznych. Oba
typy bibliotek zawierają zbiór skompilowanych podprogramów, które służą różnym
programom. W przypadku linkowania statycznego, program linkujący kopiuje potrzebne
podprogramy z pliku bibliotecznego (.LIB) i łączy je z innymi modułami tworząc w rezultacie
program wykonywalny (.EXE). Natomiast w przypadku linkowania dynamicznego
podprogramy (funkcje) biblioteczne nie są kopiowane do pliku .EXE, lecz zostają
umieszczone w specjalnym pliku, w formie przygotowanej do wywołania przez inny program,
zwany klientem. Podprogramy i dane zawarte w takich plikach noszą nazwę bibliotek
linkowanych dynamicznie (ang. dynamic-link libraries), w skrócie DLL.
W rezultacie zmniejsza się rozmiar pliku .EXE, i jednocześnie oprogramowanie staje
się bardziej elastyczne i podatne zmiany. Przykładowo, wprowadzenie ulepszonej wersji
podprogramu bibliotecznego wymaga jedynie zmiany pliku .DLL, podczas gdy programy w
formacie .EXE, które korzystają z tego podprogramu pozostają niezmienione.
Jeśli jakikolwiek klient (program) wyrazi chęć wywołania podprogramu
bibliotecznego, wówczas system operacyjny wprowadza bibliotekę do pamięci operacyjnej,
tworząc jednocześnie odpowiednie powiązania adresowe, tak by instrukcja CALL wykonana
przez klienta powodowała wywołanie właściwego podprogramu. Jeśli inni klienci wyrażą
chęć dostępu do podprogramu, to system operacyjny wykona także odpowiednie powiązania
adresowe. Tak więc pojedynczy podprogram biblioteczny może służyć kilku różnym
programom (czasami mówi się, że podprogram jest współdzielony przez te programy).
W systemie Windows biblioteki DLL dostarczają funkcji i zasobów, które mogą być
używane przez różne programy i inne biblioteki DLL. Podprogramy wchodzące w skład
bibliotek nie stanowią samodzielnych programów, jak również nie są przystosowane do
przyjmowania komunikatów.
3
Podprogramy (funkcje) wchodzące w skład DLL nie różnią się istotnie od innych
funkcji bibliotecznych. W każdej bibliotece DLL obok właściwych funkcji musi być także
zdefiniowana funkcja DllEntryPoint (w trybie 16-bitowym używa się funkcji LibMain i
WEP). Funkcja ta umożliwia programiście przeprowadzenie inicjalizacji funkcji
bibliotecznych. Funkcja DllEntryPoint jest wywoływana przez system Windows
bezpośrednio po załadowaniu biblioteki do pamięci, przed usunięciem z pamięci, a także przy
dołączaniu i odłączaniu procesu, jak również przy tworzeniu i kasowaniu wątku. Prototyp
omawianej funkcji ma postać
BOOL WINAPI DllEntryPoint (HINSTANCE hinstDLL , DWORD fdwReason ,
LPVOID lpvReserved) ;
gdzie
hinstDLL uchwyt modułu DLL  może być używany przy wywoływaniu innych funkcji;
fdwReason kod opisujący przyczynę wywołania funkcji, np. DLL_PROCESS_ATTACH
oznacza, że biblioteka DLL została dołączona do przestrzeni adresowej bieżącego
procesu jako rezultat uruchomienia procesu lub wskutek wykonania funkcji
LoadLibrary; podobnie, kod DLL_PROCESS_DETACH oznacza, że biblioteka
DLL zostaje odłączona od przestrzeni adresowej procesu wskutek jego zakończenia
lub wykonania funkcji FreeLibrary; zdefiniowane są także kody związane z
operacjami na wątkach;
lpvReserved parametr opisuje dalsze cechy procesu dołączania i odłączania biblioteki, np.
przyjmuje wartość NULL w przypadku, poprzedni parametr przyjmuje wartość
DLL_PROCESS_ATTACH i biblioteka ładowana jest dynamicznie;
Funkcja DllEntryPoint nie musi udzielać odpowiedzi na wszystkie możliwe wartości
parametru fdwReason  dla niektórych może podejmować działania, inne zaś może
ignorować. W wielu przypadkach czynności realizowane przez funkcję DllEntryPoint
ograniczają się tylko do przekazania wartości TRUE lub FALSE za pomocą instrukcji
return, a parametry funkcji są ignorowane. W tej sytuacji kompilator będzie wysyłał
ostrzeżenia informujące, że parametry funkcji są nieużywane. Ostrzeżenia te można
wyeliminować poprzez umieszczenie przed funkcją wiersza
#pragma argsused
Plik biblioteczny powinien zaczynać się od wiersza
#include
Następnie umieszcza się funkcję DllEntryPoint, a za nią właściwe funkcje biblioteczne. W
trybie 32-bitowym przyjmuje się zwykle konwencję przekazywania parametrów "stdcall".
Oznacza, to że nagłówek funkcji powinien mieć postać:
float _stdcall pole_kola (float r)
Funkcje definiowane w bibliotece DLL powinny mieć przypisaną własność
eksportowalności. Można to zrealizować poprzez umieszczenie listy funkcji w pliku
definicyjnym .DEF w sekcji EXPORTS. Przykładowy plik definicyjny może wyglądać
następująco:
LIBRARY GEOMETR
DESCRIPTION 'Przyklad biblioteki DLL'
EXPORTS pole_kola
pole_kwadratu
obwod_kola
obwod_kwadratu
4
Po napisaniu pliku zawierającego funkcje biblioteczne można wykonać jego kompilację, która
w omawianym przykładzie wymaga użycia polecenia
bcc32 -c -WD arytm32c.c
W następnym kroku wykonuje się linkowanie:
tlink32 -Tpd c0d32.obj + geometr.obj, geometr.dll, , \
import32.lib + cw32.lib, geometr.def
Znak \ umieszczony na końcu wiersza jest znakiem kontynuacji i oznacza, że dalszy ciąg
polecenia podany jest w następnym wierszu. Opcja -Tpd oznacza tworzenie pliku
wykonywalnego DLL w formacie PE.
Dodajmy, że utworzona biblioteka DLL może być używana zarówno przez programy
w Pascalu jak też przez programy w języku C.
Korzystanie z bibliotek dynamicznych
Podprogramy (lub inne dane) zawarte w bibliotekach dynamicznych wywoływane są
dopiero podczas wykonywania programu. Zatem w procesie linkowania można by pominąć
całkowicie nazwy tych podprogramów. Jednakże linker będzie przypuszczał, że programista
po prostu zapomniał podać nazwę odpowiedniej biblioteki statycznej i będzie sygnalizował
błąd. Trzeba więc udostępnić linkerowi "pseudo-bibliotekę", która będzie zawierała tylko
nazwy podprogramów. Innym rozwiązaniem jest umieszczenie listy podprogramów (w sekcji
IMPORTS) w pliku definicyjnym .DEF.
Taką "pseudo-bibliotekę" (ang. import library) tworzy się za pomocą programu
narzędziowego IMPLIB (oferowanego zarówno przez firmę Microsoft jak i Borland). IMPLIB
tworzy plik .LIB na podstawie pliku DLL. Między innymi plik IMPORT32.LIB, używany
przy linkowaniu programów, zawiera opisy podprogramów zawartych w standardowych
bibliotekach DLL systemu Windows.
Przykładowo, jeśli dysponujemy plikiem bibliotecznym MOSTY.DLL, to w wyniku
wywołania programu
implib mosty.lib mosty.dll
uzyskamy plik MOSTY.LIB. Z kolei plik MOSTY.LIB może być użyty przy linkowaniu tak
jak gdyby była to zwykła biblioteka czasu wykonania, np.
tlink32 . . . . ., . . . + mosty.lib, klient.def
System Windows poszukuje wskazanej biblioteki DLL kolejno przeglądając:
" bieżący katalog;
" katalog, w którym zawarty jest plik WIN.COM;
" katalog systemowy Windows;
" katalog, w którym znajduje się program klienta;
" katalogi podane w wierszu PATH w bloku otoczenia;
" dołączone katalogi sieciowe.
Jeśli biblioteka nie znajduje się w żadnym z tych katalogów, to sygnalizowany jest błąd.
Biblioteki dynamiczne w środowisku oprogramowania firmy Microsoft
5
Tworzenie i wykorzystanie bibliotek dynamicznych w środowisku Microsoft
pokażemy na przykładzie. W stosunku do omówionego wcześniej środowiska Borland
występują niewielkie różnice dotyczące zwłaszcza parametrów konsolidatora.
Program główny wykonuje proste obliczenie na liczbach całkowitych, przy czym
potrzebne wartości obliczane są przez funkcje zdefiniowane w biliotece dynamicznej DLL.
Poniżej podano kod programu głównego (plik glowny.c).
#include
#include "arytm32.h"
int main ( )
{
int i, j;
printf ("\n\n Prosze podac dwie liczby calkowite: ");
scanf ("%d %d", &i, &j);
printf("\nSuma liczb %d i %d wynosi %d, a suma ich kwadratow %d",
i, j, sumazw(i,j), sumakw(i,j));
printf("\nRoznica liczb %d i %d wynosi %d, a roznica ich kwadratow %d",
i, j, roznicazw(i,j), roznicakw(i,j));
return 0;
}
Plik nagłówkowy arytm32.h zawiera prototypy funkcji bibliotecznych i ma postać:
extern int _stdcall sumazw (int x, int y);
extern int _stdcall sumakw (int x, int y);
extern int _stdcall roznicazw (int x, int y);
extern int _stdcall roznicakw (int x, int y);
Podane niżej funkcje, zakodowane w języku C, wejdą w skład biblioteki dynamicznej
arytm32.dll. Dodatkowa funkcja DllEntryPoint jest niezbędna dla poprawnej pracy
biblioteki. W bardziej skomplikowanych bibliotekach funkcja ta służy do inicjalizacji i
deinicjalizacji biblioteki (np. do przydzielania i zwalniania pamięci).
(plik sumy.c)
#include
BOOL WINAPI DllEntryPoint (HINSTANCE hinstDLL ,
DWORD fdwReason , LPVOID lpvReserved)
{
return(TRUE);
}
int __declspec(dllexport) _stdcall sumazw (int a, int b)
{ int w; w = a + b; return (w); }
int __declspec(dllexport) _stdcall sumakw (int a, int b)
{ int w; w = a*a + b*b; return (w); }
(plik roznice.c)
int __declspec (dllexport) _stdcall roznicazw (int a, int b)
{ int w; w = a - b; return(w); }
6
int __declspec (dllexport) _stdcall roznicakw (int a, int b)
{ int w; w = a*a - b*b; return (w); }
W celu utworzenia biblioteki dynamicznej trzeba najpierw przeprowadzić kompilację plików
zawierających funkcje biblioteczne. W celu ułatwienia wywoływania kompilatora i
konsolidatora uruchamia się najpierw plik vcvars32.bat, który konfiguruje ścieżki dostępu.
Postać wywołania tego pliku w laboratoriach komputerowych w nowym gmachu Wydziału
ETI PG ma postać:
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
Po wywołaniu pliku vcvars32.bat uruchomienie kompilatora wymaga tylko podania jego
nazwy. Polecenia kompilacji plików zawierających funkcje biblioteczne mają postać:
cl -c sumy.c
cl -c roznice.c
W wyniki kompilacji powstaną plikisumy.obj i roznice.obj, z których za pomocą
konsolidatora link tworzy się bibliotekę dynamiczną arytm32.dll. Dodatkowo
konsolidator tworzy także plik arytm32i.lib, który zawiera informacje potrzebne do
konsolidacji programu głównego (plik arytm32i.lib zawiera nazwy funkcji
bibliotecznych bez kodu). Poniżej podano postać polecenia, które wykonuje omówione
operacje (polecenie to należy napisać w jednym wierszu):
link -out:arytm32.dll -DLL -IMPLIB:arytm32i.lib
sumy.obj roznice.obj
Z kolei należy przeprowadzić kompilację i konsolidację programu głównego:
cl -c glowny.c
link -subsystem:console -out:glowny.exe glowny.obj arytm32i.lib
Wszystkie omówione tu operacje można opisać razem w postaci pliku makefile 
poniżej podano postać tego pliku. Polecenia zawarte w tym pliku zostaną wykonane po
uruchomieniu programu nmake (bez parametrów).
# Tworzenie i testowanie biblioteki dynamicznej
# Funkcje biblioteczne testowane sa za pomoca programu glowny.c
# kwiecien 2008
# tworzenie programu do testowania
glowny.exe : glowny.obj arytm32i.lib
link -subsystem:console -out:glowny.exe glowny.obj arytm32i.lib
glowny.obj : glowny.c
cl -c glowny.c
# tworzenie biblioteki arytm32.dll i i biblioteki "import" arytm32i.lib
arytm32i.lib : sumy.obj roznice.obj
link -OUT:arytm32.dll -DLL -IMPLIB:arytm32i.lib sumy.obj
roznice.obj
sumy.obj : sumy.c
7
cl -c sumy.c
roznice.obj : roznice.c
cl -c roznice.c


Wyszukiwarka

Podobne podstrony:
4 Statyczne i dynamiczne wlasciwosci regulatorow
statyczne dynamiczne
Rozdział 3 Analiza statyczna i dynamiczna wybranych mostów 3 1 Cel i zakres analizy numerycznej
BADANIE STATYCZNYCH I DYNAMICZNYCH WŁAŚCIWOŚCI REGULATORÓW PID
Statyczne I Dynamiczne Obciazenie Tranzystora
Konfiguracja protokolow routingu statycznego i dynamicznego
W asno ci statyczne i dynamiczne pneumatycznych przetwornikow pomiarowych
311[15] O1 04 Wykonywanie obliczeń w układach statycznych, dynamicznych i kinematycznych
Biblioteka dll
Wyłaczenie bibliotek DLL przyśpiesza kompa
2 Ocena obciążenia fizycznego podczas pracy wysiłek dynamiczny statyczny monotypowość ruchów wydolno
5 29 Praca z bibliotekami DLL (2)

więcej podobnych podstron