Автор работы: Пользователь скрыл имя, 06 Апреля 2014 в 10:25, курсовая работа
Бағдарламалау технологиясының дамуына байланысты көптеген адамдар өздерінің бағдарламаларының мүмкіндіктерін жоғарлату қателіктерімен соқтығысып жатады. Осы менің курстық жұмысым осы сұраққа арналған, яғни Borland Delphi тілінде DLL – ді бағдарламауға. Сонымен қоса, DLL кітапханаларын пайдалану туралы сұрақтарды қарастырғанда, біз басқа DLL – дан импорттауды да қарастырып кетеміз.
Бұл процедураны қосымшаның параметрінен шақырған кезде қосымша классының экземплярын көрсету керек:
procedure ShowDemoForm(AOwner: TComponent); external 'DataCtrl.dll';
procedure TMainForm.BitBtnlClick(Sender: TObject);
begin
ShowDemoForm(Application);
end;
Берілген жағдайда динамикалық кітапханадағы форма операциялық жүйеде жеке тапсырма ретінде қаралатындыына назар аударыңыз.
Delphi репозиториясында динамикалық
кітапханаларды құру үшін
2.1-сурет. Delphi-де DLL құру үшін File -> New ->Other командасын орындау сұлбасы
2.2-сурет. File -> New ->Other командасын орындағаннан кейін ашылған DLL шеберін таңдау терезесі
Осы 2.1 - сурет және 2.2 – суреттерде көрсетілген қадамдардан кейін Delphi ұзақ комментарийлі арнайы проект терезесін ашады. Бұл терезеде ShareMem модуліне міндетті түрде өту керектігін көрсетеді. Бұл өту кітапхананың uses қосымшасында бірінші болуы керек. Егер кітапхананың қосымша бағдарламалары ShortString немесе Pchar жолдарын экспорттаса, онда ShareMem ға өту маңызды емес. Бұл жерде проектіні Сmpix деген атпен сақтау керек. Бұлай сақтау себебі Delphi кітапхана құрған кезде Library бөлімінде сол сақталған атпен автоматты түрде кітапхана құрады.
DLL жұмысқа дайын процедуралардан,
функциялардан немесе
Object Pascal - да DLL - ді құру үшін Library деген сөз енгізілген. Бұл сөзбен кітапхана мәтіні басталуы керек. Library деген сөзден дұрыс идендификатор тұрады, бірақ модульді шақырудан айырмашылығы ол файл атымен сәйкес келмеуі керек: DLL аты идентификатормен емес DLL файл атымен анықталады.
DLL мәтінінің құрылымы
қарапайым бағдарламаның
2.3-сурет. Жадыдағы DLL - дің құрылымы
DLL-ді сипаттау бөлімінде типтер (сонымен қоса класстарда), константалар және айнымалылар хабарлануы мүмкін, бірақ олар шақырылған бағдарлама үшін жасырын болып қала береді және DLL ішінде ғана қолданыла алады. Сипаттау бөлімінде қарапайым бағдарламаға арналған стандартты шақырулардан басқа экспортталатын қосымша бағдарламалар үшін арнайы бөлім қолданылады. Бұл бөлім Exports сөзінен басталады және бұл сөзден кейін үтір арқылы экспортталатын қосымша бағдарламалар аттары жазылады. Мысалы:
library MyLibrary;
function MyFunc(...): ...;
begin
end;
procedure MyProc;
begin
end;
exports
MyFunc, MyProc;
begin
end.
Exports бөлімі кампиляторға және компоновщике DLL-модулі үшін арнайы тақырыбын құруға көмектеседі. Бұл модульде қосымша бағдарламалардың және олардың ену нүктелерінің адресстернің аттары жазылады. DLL-де Exports тың бірнеше тізімі болуы мүмкін, бірақ ондағы жазылған қосымша бағдарламалар жоғарыда кітапхана мәтінінде сипатталуы керек.
DLL тақырыпшасындағы қосымша бағдарламалар атынан басқа оның реттік номері, яғни, оған арналған индексі де қосылады. Бұл шақырылған бағдарламаға қосымша бағдарламаға өту үшін онын аты емес индексі арқылы өтуді іске асырады. Және сонымен қоса онымен байланыс орнатуға кететін уақытты азайтуға да мүмкіндік береді. Индекс қосымша бағдарлама Exports тізімінде пайда болғаннан бастап беріледі: тізімдегі бірінші қосымша бағдарлама 0 деген индекске ие болады, келесісі - 1 және т.с.с. Бағдарлама құрушы бұл индексацияны өзгерте алады және қосымша бағдарламаларға индексін көрсете алады. Ол үшін ол Exports тізімінде онын атымен index деген сөзді енгізу арқылы және 0 - ден 32767 - ге дейінгі нақты сандарды белгілерсіз енгізу арқылы қосымша бағдарлама индексін өзгерте алады:
exports
MyFunc index 1, MyProc index 2;
Бағдарламашы экспортталатын бағдарламаның негізгі атынан айырып тұратын сыртқы атын сипаттай алады. Бұл үшін Exports тізіміне name және сыртқы ат тырнақша ішінде жазылуы арқылы енгізуге болады:
exports
MyFunc index I name 'NEWFUNC';
Шақырылатын бағдарлама экспортталатын қосымша бағдарлама атына немесе онын индексіне өте алады. Аты арқылы шақырған кезде бағдарлама кесте ішінен ізделінетін атқы сәйкес ат іздейді. Аттардың ұзақ символдардан тұруы және бірдей аттардың кестеде көп болу мүмкіншілігіне байланысты аты арқылы іздеу процессі индекс арқылы іздеу процессіне қарағанда жай болады. Сондықтан дәрежелі бағдарламаушылар қосымша бағдарламаларға аты арқылы емес индексі арқылы өтуді таңдайды.
Қарап отырсаңыз, Delphi дің модульдерден айырмашылығы олар DLL ді make немесе build, т.с.с. автоматты режимдерінде компилациядан өткізбейді. Мысал
DLL-ді құру мысалын қарастырып кетейік, бұл мысалда экспортталатын қосымша бағдарламаларды хабарлаудың әртүрлі тәсілдері құрылады. Мысал үшін cmpix модулін таңдайық. Оның құрамына төрт процедура кіреді. DLL-ге сәйкес келетін нұсқа төменде көрсетілген.
library Cmpix;
uses
SysUtils, Classes;
{$R *.RES}
type
TComplex = record Re, Im: Real;
end;
function AddC(x, y: TComplex): TComplex; stdcall;
begin
Result.Im := x.Im + y.Im;
Result.Re := x.Re + y.Re
end;
function SubC(x, y: TComplex): TComplex; stdcall;
begin
Result.Im := x.Im - y.Im;
Result.Re := x.Re - y.Re
end;
function MulC(x, у: TComplex): TComplex; stdcall;
begin
Result.Re := x.Re * y.Re + x.Im * y.Im;
Result.Im := x.Re * y.Im - x.Im * y.Re
end;
function DivC(x, y: TComplex): TComplex; stdcall;
var
z: Real;
begin
z := sqr(y.Re) + sqr(y.Im);
try
Result.Re := (x.Re * y.Re + x.Im * y.Im) / z;
Result.Im := (x.Re * y.Im - x.Im * y.Re) / z
except
Result.Re := le + 309;
Result.Im := le + 309
end
end;
exports
AddC index 1 name 'ADDC' resident,
SubC index 2,
MulC index 3,
DivC index 4;
begin
end.
Бұл жерде назар аударатын жағдай DLL - дің барлық функциялары stdcall келісімін пайдаланады. Бұл келісім жаңа функциялардың API Windows 32 функцияларыменен сәйкес келулерін қамтамассыз етеді. Біз бұл келісімді көрсетпей кетуімізге де болатын еді. Бірақ бұл жағдайда компилятор бұл келісімнен мықтырақ келісім register келісімін пайдаланар еді, бірақ біздің DLL-ді басқа бағдарламалау тілдерінде жазылған бағдарламадан шақыру жалпы жағдайда мүмкін болмай кетер еді.
Егер сіз DLL - ді «сыртқы» жағдайда (Delphi - ден тыс), қолдану үшін құрсаңыз, онда қосымша бағдарламаларды stdcall немесе safecall директиваларымен хабарлаңыз.
Қолданылуы. Статикалық жүктеу. Келесі бағдарламада Сmpix кітапханасы қолданылады. Бұл кітапхана алдыңғы беттерде сипатталып кеткен.
type
TComplex = record
Re, Im: Real;
end;
function ADDC(x, y: TComplex): TComplex; stdcall; external 'Cmplx';
function SubC(x, y: TComplex): TComplex; stdcall; external 'Cmplx';
function MulC(x, y: TComplex): TComplex; stdcall; external 'Cmplx';
function DivC(x, y: TComplex): TComplex; stdcall; external 'Cmplx';
procedure TfmExample.bbRunClick(Sender: TObject);
var
x, y, z: TComplex;
cmpixAdd кітапханалық функциясы
addc сыртқы атына ие болатынына
назар аударған жөн. Дәл осылай
жоғарыдағы мысалда бұл
function AddC(x, у: TComplex): TComplex; stdcall; External
'Cmplx';
Динамикалық жүктеу. Жоғарыда көрсетілген DLL функциялары мен процедураларын анықтау (External директиваларының көмегімен) тәсілі компиляторды бағдарламалар тақырыпшасына барлық DLL-ді орналастыруды талап етеді. Бағдарлама External директивасысыз DLL-ді үш стандартты функция көмегімен жүктей алады.
Ол стандартты функциялар: LoadLibrary, GetProcAddress және FreeLibrary.
Келесі мысалда DLL Cmplx ті осындай техникамен жүктеу көрсетілген:
type
TComplex = record
Re, Im: Real;
end;
TComplexFunc = function(x, y: TComplex): TComplex; stdcall;
procedure TfmExample.bbRunClick(Sender: TObject);
var
x, y, z: TComplex;
AddC, SubC, MulC, DivC: TComplexFunc;
Handle: LongWord;
procedure Output(Operation: Char);
// Output процедурасының денесі өзгеріссіз қалады
end; //Output
begin //bbRunClick
// CMPLX.DLL Handle := LoadLibrary('Cmplx.dll') кітапханасын жүктейміз;
if Handle = 0 then
begin
ShowMessage('CMPLX.DLL кіиапханасы табылмады');
Halt
end;
{Функциялардың адресстерін анықтаймыз. Алғашқы үшеуін индексі арқылы шақырамыз, төртіншісін – аты арқылы, индексі арқылы шақырған кезде Pchar сөзі индекстен тұруы керек, сондықтан алдымен типтерді анықтауды жасаймыз: }
@AddC := GetProcAddress(Handle, PChar(Longint(1)));
PSubC := GetProcAddress(Handle, PChar(Longint(2)));
@MulC := GetProcAddress(Handle, PChar(Longint(3)));
@DivC := GetProcAddress(Handle, 'DivC');
x.re := Random;
x.im := Random;
y.re := Random;
y.im := Random;
Output('+');
Output('-');
Output('*');
Output('/');
mmOutput.Lines.Add('');
// FreeLibrary(Handle) кітапханасын босатамыз
end;
DLL- қосымша бағдарламаларды
шақырған кезде көптеген
unit Complx;
interface
type
TComplex = record
Re, Im: Real;
end;
function AddC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 1;
function SubC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 2;
function MulC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 3;
function DivC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 4;
implementation
end.
Мұндай интерфейстік модуль негізгі бағдарламаны өндеуді оңайлатыды: біздің мысалда ол cmpix кітапханасына дәл осындай интерфейспен қамтамассыздандырады.
Delphi де құрылған DLL-дегі туындайтын шектеулі жағдайлар барлық қосымшалардың іске асуын тоқтатуға әкеп соғады. Бұл жағдайлар DLL-дің ішінде өнделмеген болған жағдайда. Сондықтан DLL-ді құрған кезде барлық мүмкін болатын қателіктерді қарастырып кеткен жөн. Импортталатын функцияның жол немесе сан түріндегі іске асқан шешімін қайтаруды ұсынуға болады және де керек болған жағдайда бағдарламадағы шектеулі жағдайларды қайтадан шақыруға болады.
DLL-дегі код:
function MyFunc : string;
begin
try
{собственно код функции}
except
on EResult: Exception do
Result:=Format(
[EResult.Message]);
else
Result := Format(DllErrorViewingTable,
['Unknown error']);
end;
end;
Бағдарламадағы код:
StrResult:=MyFunc;
if StrResult<>'' then
raise Exception.Create(StrResult);