|
formula doua sau mai multe variante de compilare a datelor din aceeasi
|
səhifə | 23/24 | tarix | 03.11.2017 | ölçüsü | 2,15 Mb. | | #28851 |
| formula doua sau mai multe variante de compilare a datelor din aceeasi
unitate sursa.Nu este bine,totusi,sa abuzati de prea multe directive de
acest gen,sau sa formulati bucle de selectie a datelor prea complicate,
deoarece unitatile vor fi incomprehensibile pentru alti programatori care
ar fi eventual interesati sa le utilizeze.Este bine ca atunci cand decla-
rati o unitate noua,sa aveti in vedere faptul sa ar putea sa fie utila si
pentru alte programe,sau alti utilizatori.In acest sens,este bine ca
datele declarate sa fie incluse in constante si variabile cu denumiri cat
mai discriminative (se vor evita identificatorii de tip x,y,a,b,c etc si
se vor prefera cei de tipul: variabilax1,variabilax2 etc.) astfel incat
sa se evite pe cat posibil conflictul de nume cu eventualele constante si
variabile din programul care apeleaza unitatea.
Buclele de compilare conditionala pot fi utilizate cu succes pentru
a selecta din unitatile declarate de altii,doar un fragment,cel care este
util in programul d-voastra.Astfel,se economiseste munca de programare
si memoria de operare.Reciproc,trebuie ca unitatile declarate de d-voastra
sa poata fi apelate conditional de catre alti utilizatori (datele trebuie
sa fie clare,expresiile cat mai simple si cat mai usor de evaluat,etc.).
-189-
Pentru a forma biblioteci,doua sau mai multe unitati se grupeaza cu uses:
EXEMPLU: unit unit9;
INTERFACE
uses WinCRT,WinProcs,WinTypes;
var w,h,nr,b:integer;
t1,t2,t3:longint;
IMPLEMENTATION
begin
Randomize;
InitWinCRT;
w:=GetActiveWindow;
h:=GetDC(w);
t1:=GetCurrentTime;
repeat
b:=CreateSolidBrush(RGB(Random(255),Random(255),Random(255)));
SelectObject(h,b);
Ellipse(h,100,100,200,200);
t2:=GetCurrentTime;
repeat
t3:=GetCurrentTime;
until t3>t2+1000;
until t2>t1+10000;
end.
Unitatea poate fi apelata cu un program de genul:
EXEMPLU: program prog9;
uses unit9;
begin
end.
Si o a doua unitate similara (in exemplu este derivata din prima):
EXEMPLU: unit unit10;
INTERFACE
uses WinCRT,WinProcs,WinTypes;
var w1,h1,nr1,b1:integer;
t11,t21,t31:longint;
IMPLEMENTATION
begin
Randomize;
InitWinCRT;
w1:=GetActiveWindow;
h1:=GetDC(w1);
t11:=GetCurrentTime;
repeat
b1:=CreateSolidBrush(RGB(Random(255),Random(255),Random(255)));
SelectObject(h1,b1);
Rectangle(h1,350,100,450,200);
t21:=GetCurrentTime;
repeat
t31:=GetCurrentTime;
until t31>t21+1000;
until t21>t11+10000;
end.
-190-
Cea de a doua unitate se poate apela cu:
EXEMPLU: program prog10;
uses unit10;
begin
end.
Pentru a utiliza ambele unitati se poate scrie un program de genul:
EXEMPLU: program prog11;
uses unit9,unit10;
begin
writeln('Sfarsitul compilarii celor doua unitati !');
writeln('Incepe programul propriu zis...');
end.
Pentru a forma o biblioteca,cele doua unitati pot fi grupate intr-o sin-
gura unitate,care le apeleaza pe amandoua in etapa de INTERFACE,prin
instructiunea uses.
EXEMPLU: unit unit11;
INTERFACE
uses unit9,unit10;
IMPLEMENTATION
begin
end.
In continuare,pentru a utiliza cele doua unitati este suficient sa fie
apelata biblioteca care le cuprinde pe amandoua:
EXEMPLU: program prog12;
uses unit11;
begin
end.
In mod similar se pot grupa un numar mai mare de unitati,pentru a forma
biblioteci mai complexe.In exemplele de mai sus,unitatile executa si o
serie de operatii in etapa de initializare,pentru a evidentia cat mai
clar de unde si pana unde dureaza compilarea fiecarei unitati (prima ge-
nereaza cercuri colorate aleator,iar cea de a doua genereaza patrate.
Observati ca unitatile apelate se incarca o singura data in memorie si
orice apel ulterior suprascrie acelasi fragment de memorie:
EXEMPLU: program prog13;
uses unit9,unit10,unit11;
begin
end.
este identic cu prog12.Ca rezultat,unitatile pot fi apelate ori de cate
ori este necesar fara riscul de a supraincarca memoria prin rescrierea
acelorasi unitati.Totusi,este preferabil ca fiecare unitate sa fie apelata
o singura data,deoarece repetitia iterativa introduce operatii inutile
care cresc nejustificat uzura aparaturii.In plus,este bine ca fiecare
programator sa tina o evidenta cat mai stricta a memoriei consumate.Daca
va bazati doar pe sistem in gestiunea memoriei,mai devreme sau mai tarziu
puteti avea si surprize neplacute.
Gruparea unitatilor sub forma de biblioteci,adauga putina eleganta in
munca de ordonare a datelor si formeaza un obicei bun.In mod similar,in
cazul bibliotecilor alocate dinamic (DLL),toate functiile importate din
biblioteci diferite se pot grupa intr-o biblioteca(unitate) de import.
-191-
BIBLIOTECILE ALOCATE DINAMIC (DLL)
Bibliotecile alocate dinamic,denumite prescurtat DLL(dynamic link li-
braries),sunt asemanatoare cu cele statice dar au cateva particularitati.
Orice biblioteca DLL incepe cu cavantul cheie library (in loc de unit sau
program) care determina compilatorul sa genereze o fila cu extensia .dll.
Asa cu le spune si numele,aceste biblioteci nu sunt incarcate in memorie
in momentul compilarii programului ci doar in momentul executiei.
Principalul scop al acestor biblioteci este de a permite mai multor
programe si aplicatii sa utilizeze acelasi set de date sau aceleasi coduri
functii si proceduri sau chiar obiecte.O biblioteca DLL este un modul
executabil,independent si poate contine pe langa coduri si resurse proprii
(gen icoane,cursoare,arii bitmap,tabele etc.).Prezenta bibliotecii este
obligatorie atunci cand un program apeleaza o astfel de biblioteca.Astfel,
daca intr-un program exista functii declarate EXTERNAL,care importa defi-
nitia dintr-o fila de tip .dll,este obligatoriu ca fila .dll sa fie pre-
zenta in momentul compilarii,chiar daca nu va fi incarcata in memorie si
nu va fi utilizata in cursul executiei programului(functiile raman neape-
late).Aceasta este si principala deficienta introdusa de utilizarea unor
astfel de biblioteci (daca se sterge din greseala una dintre bibliotecile
DLL apelate,programul respectiv nu mai poate fi utilizat).
In schimb,actualizarea sau modificarea unei file DLL va atrage dupa sine
actualizarea tuturor programelor si aplicatiilor care utilizeza fila res-
pectiva.In plus,bibliotecile DLL nu consuma din memoria de operare si nu
sunt incarcate in memorie decat strict functiile apelate si doar in mo-
mentul in care sunt apelate.
Spre deosebire de bibliotecile statice,bibliotecile DLL nu exporta
toate datele ci doar pe cele specificate expres prin cuvantul cheie
EXPORT si respectiv incluse in lista de export introdusa cu ajutorul
cuvantului cheie EXPORTS.Asadar,o biblioteca DLL poate contine atat date
interne (care pot fi apleate doar in interiorul filei DLL) cat si date
(functii,proceduri,obiecte) care pot fi exportate in alte module.
Toate variabilele globale dintr-o fila DLL sunt strict interne si nu
pot fi exportate.Clasic,bibliotecile DLL exporta doar functii si proce-
duri,dar se poate apela la un mic artificiu prin care o functie oarecare
returneaza o valoare de tip obiect,caz in care obiectul respectiv poate
fi exportat.
Legatura(link) dintre programul apelant si fila DLL care contine defi-
nitia functiilor exportate se face in momentul compilarii programului (
chiar daca incarcarea in memorie se va face doar in momentul executiei !).
Bibliotecile DLL pot fi partajate nu doar de catre utilizatori si pro-
grame diferite scrise in Pascal,dar pot fi utilizate si de catre programe
scrise in alte limbaje (C si C++,Delphi,Oracle,Visual Basic etc.) cu
conditia sa utilizeze aceleasi conventii de apel si respectiv sa contina
doar functii comune pentru ambele limbaje (de exemplu functiile Windows).
Principalele conventii de apel sunt:REGISTER,CDECL,STDCALL,SAFECALL si
PASCAL.Register,este conventia implicita si transfera parametrii de la
dreapta la stanga in timp ce CDECL,STDCALL si SAFECALL transfera para-
metrii de la stanga la dreapta.CDECL se utilizeaza in bibliotecile DLL
scrise in C si C++ iar STDCALL si SAFECALL sunt utile mai ales pentru
cele care contin functii Windows API.
-192-
O biblioteca DLL se editeaza la fel ca un program obisnuit,dar se
incepe cu cavantul cheie library urmat de numele bibliotecii(identificator)
Functiile si procedurile care urmeaza sa fie exportate se specifica expres
adaugand cuvantul cheie EXPORT la sfarsitul declaratiei,iar la sfarsitul
etapei de implementare se adauga un modul de export care incepe cu cuvant-
ul cheie EXPORTS si continua cu lista functiilor si procedurilor exportate
EXEMPLU:
library bibdll1;
function Mesaj:PChar;export;
begin
mesaj:='Text preluat din biblioteca bibdll1';
end;
exports
Mesaj;
begin
end.
Utilizarea bibliotecii se poate face cu un program de genul:
EXEMPLU:
program progdll1;
uses WinCRT;
function Mesaj:PChar;external 'bibdll1';
begin
writeln(mesaj);
end.
Observati ca pentru a importa functia dorita din fila DLL,am utilizat
cuvantul cheie external,urmat de numele bibliotecii(identificatorul).
Este foarte simplu !
Atunci cand biblioteca contine un numar mai mare functii care urmeaza
sa fie exportate,se poate adauga un index pentru a identifica mai usor
fiecare functie (mai ales in etapa de depanare a programului).
EXEMPLU:
library bibdll2;
function Min1(x,y:integer):integer;export;
begin
if x
end;
function Max1(x,y:integer):integer;export;
begin
if x>y then Max1:=x else Max1:=y;
end;
exports
Min1 index 1,
Max1 index 1;
begin
end
Observati ca in modulul de export,cele doua functii exportate au primit si
un numar de indexare cu ajutorul caruia pot fi identificate mult mai
discriminativ.Clauza de indexare este facultativa iar numarul de indexare
poate fi orice numar de tip unsigned int (1-32767).Daca nu se specifica
numarul de indexare,functia va avea un numar de ordine atribuit automat.
In continuare,cele doua functii vor putea fi apleate prin indexul lor:
-193-
EXEMPLU:
program progdll2;
uses WinCRT;
function Min1(x,y:integer):integer;external 'bibdll2' index 1;
function Max1(x,y:integer):integer;external 'bibdll2' index 2;
begin
writeln('minima dintre 19 si 3 este: ',Min1(19,3));
writeln('maxima dintre 99 si 7 este: ',Max1(99,7));
end.
Asadar,cele doua functii pot fi apelate atat prin numele lor (la fel
ca in primul exemplu),cat si prin numarul lor de indexare.A treia modali-
tate de a importa o functie este prin utilizarea unui nume nou fata de
cel initial(functia importata va fi redenumita prin noul identificator).
La prima vedere pare putin confuz si complicat,conform cu aforismul:
" That which is static and repetitive is boring
That which is dynamic and random is confusing
In between lies art !
John A.Locke "
Pentru a evita o mare parte din confuziile posibile,este de dorit ca
atunci cand editati biblioteci DLL pe care doriti sa le poata utiliza si
alti programatori,sa adaugati pe langa fila de explicatii,si fila de cod
sursa,cu extensia .PAS(cea care a fost compilata pentru a genera fila DLL)
Ratiunile sunt aceleasi ca si pentru unitati.In plus,bibliotecile de tip
DLL pot fi utilizate modular (utilizatorul poate alege singur functiile
pe care doreste sa le importe).Fara fila sursa este putin probabil ca
munca d-voastra sa fie utila si altor programatori.In caz ca scrieti
programe comerciale si jocuri,caz in care doriti sa pastrati secretul
codurilor si sa valorificati material munca depusa,puteti sa puneti la
dispozitie doar fila gata compilata si un sumar de explicatii si recoman-
dari,cu speranta unor castiguri viitoare (personal nu cunosc nici un mili-
onar cu bani produsi din DLL-uri).
O procedura se editeaza si exporta la fel ca si o functie.Este reco-
mandabil sa utilizati doar majuscule sau doar minuscule atunci cand
formulati numele procedurii (Exemplu: MESAJ sau mesaj in loc de Mesaj).
EXEMPLU:
library bibdll3;
uses WinCRT,WinProcs,WinTypes;
var x:integer;
procedure mesaj;export;
begin
x:=messagebox(GetActiveWindow,'Bun gasit ...DLL','mesaj',MB_OK);
end;
exports
mesaj index 1;
begin
end.
Editarea respecta aceleasi reguli ca si in cazul unitatilor.Conventiile
de limbaj sunt aceleasi.Diferenta este data de faptul ca o biblioteca
DLL poate contine si coduri interne,care nu vor fi accesibile in programul
apelant.De exemplu,variabila x din acest program nu va putea fi preluata
sau apelata in programul sau aplicatia care utilizeaza aceasta fila.
-194-
Fila DLL descrisa anterior poate fi apelata cu un program de genul:
EXEMPLU:
program progdll3;
uses WinCRT,WinProcs,WinTypes;
procedure mesaj:external 'bibdll3' index 1;
begin
InitWinCRT;
mesaj;
end.
In momentul apelului unei proceduri externe,aceasta poate sa apeleze
si procedurile interne din fila DLL (daca este cazul),inainte de a retur-
na executia la programul apelant.De exemplu,mesajul de mai sus poate fi
continut intr-o procedura interna (care nu este exportata) dar va fi pre-
luat cu ajutorul unei functii exportate:
EXEMPLU:
library bibdll4;
uses WinCRT,WinProcs,WinTypes;
var x:integer;
procedure text;
begin
x:=MessageBox(GetActiveWindow,'Bun gasit ...DLL','mesaj:',MB_OK);
end;
procedure mesaj;export;
begin
text;
end;
exports
mesaj index 1;
begin
end.
Pentru apelul functiei se va utiliza un program similar cu progdll3:
EXEMPLU: program progdll4;
uses WinCRT,WinProcs,WinTypes;
procedure mesaj;external 'bibdll4' index 1;
begin
InitWinCRT;
mesaj;
end.
Diferenta fata de fila DLL precedenta este data de faptul ca procedura
mesaj (cea exportata) apeleaza la o procedura interna (procedura text),
inainte de a returna executia la programul apelant.In mod similar,pro-
cedurile din fila DLL se pot apela intre ele,ori de cate ori este necesar
inainte de a returna controlul la fila apelanta.Atentie maxima insa,sa nu
ramana nici un proces in executie inainte de a returna controlul catre
fila apelanta.In caz contrar,procesul respectiv va ramane in executie in
background si va parazita memoria de operare pana la oprirea calculato-
rului(spre deosebire de procesele neterminate din fila de program,care se
vor intrerupe automat in momentul inchiderii programului.Orice stream
ramas deschis si orice obiect neeliberat din memorie va determina un
proces parazitar,redundant,care blocheaza memoria de operare (programul
respectiv nu va mai putea fi lansat decat dupa inchiderea calculatorului).
-195-
Filele DLL se pot utiliza si pentru aplicatiile grafice.Functiile si
procedurile se definesc la fel ca si in programe,dar cu atentie maxima
la eliberarea obiectelor definite si a variabilelor de tip handle:
EXEMPLU:
library bibdll5;
uses WinCRT,WinProcs,WinTypes;
var x:integer;
procedure desen;export;
begin
x:=GetDC(GetActiveWindow);
TextOut(x,50,10,'Aplicatie grafica:',18);
MoveTo(x,50,50);
LineTo(x,50,250);
LineTo(x,250,250);
Rectangle(x,100,100,200,200);
Ellipse(x,120,120,180,180);
ReleaseDC(GetActiveWindow,x);
end;
exports
desen index 1;
begin
end.
Fila DLL descrisa mai sus poate fi apelata cu:
EXEMPLU: program progdll5;
uses WinCRT,WinProcs,WinTypes;
var x:integer;
procedure desen;external 'bibdll5' index 1;
begin
InitWinCRT;
desen;
exit;
end.
In exemplul de mai sus,daca se omite eliberarea variabilei handle x,in
care am stocat codul pentru contextul de dispozitiv (cu GetDC() ),atunci
procesul respectiv va ramane stocat in memorie si va bloca relansarea
programului (returneaza un mesaj de eroare nedeterminat).
Pentru a evita astfel de erori,verificati cu foarte mare atentie
fiecare element la filelor DLL.Executati fiecare functie exportata de
mai multe ori si verificati cu atentie si memoria ramasa libera in urma
executiei.Orice greseala,oricat de mica,la nivelul unei biblioteci de
functii DLL se va rasfrange asupra tuturor programelor si aplicatiilor
care apeleaza biblioteca respectiva.Astfel,daca in etapa de actualizare
a unei biblioteci DLL introduceti o eroare de executie,aceasta va bloca
toate aplicatiile linkate la fila respectiva.
Din acest motiv,nu este bine sa utilizati biblioteci DLL la care nu
aveti acces la fila de coduri.Daca biblioteca nu este insotita de fila
.PAS si daca nu detineti un program care face conversia inversa,(din fila
executabila in fila .PAS)este mai bine sa nu utilizati filele DLL scrise
de altcineva,decat strict pentru scopul pentru care v-au fost livrate.
In situatii disperate,inlocuiti functia exportata cu una redefinita.
-196-
Daca utilizati o biblioteca DLL in comun cu alti utilizatori,si nu
stiti exact in ce alte aplicatii este apelata,nu incercati sa faceti
actualizari ale filei,deoarece dernajati sau chiar invalidati aplicatiile
celorlati utilizatori.Pentru filele utilizate in retea,toate actualizarile
si modernizarile sunt rezervate administratorului de retea.
La fel ca si in cazul unitatilor,se poate utiliza si blocul de initia-
lizare situat in interiorul buclei begin ... end.In acest caz,toate co-
mezile si instructiunile din acest compartiment se vor executa in etapa
de compilare (ca si in cazul unitatilor,legatura dintre aplicatie si
fila DLL=linkarea,se face in etapa de compilare).
EXEMPLU:
Dostları ilə paylaş: |
|
|