Автор работы: Пользователь скрыл имя, 06 Апреля 2014 в 10:25, курсовая работа
Бағдарламалау технологиясының дамуына байланысты көптеген адамдар өздерінің бағдарламаларының мүмкіндіктерін жоғарлату қателіктерімен соқтығысып жатады. Осы менің курстық жұмысым осы сұраққа арналған, яғни Borland Delphi тілінде DLL – ді бағдарламауға. Сонымен қоса, DLL кітапханаларын пайдалану туралы сұрақтарды қарастырғанда, біз басқа DLL – дан импорттауды да қарастырып кетеміз.
DLL-де функциялар мен процедураларды ғана сақтауға болмайды, сонымен қоса барлық мүмкін болатын кескіндер, белгілер және т.б. жатады. DirectX, OpenGl сияқты танымал пакеттер кітапхана қолдауына жатады.
Бағдарлама бөліктерінде формаларды сақтауға болады. Плагиндар бұлар бағдарламаға оны жеңілдететін қосымша. Бөлінетін ресурстар арқасында DLL бірнеше бағдарламамен немесе процесстермен орындалуы мүмкін.
DLL жұмыс жасайтын функциялар мен қадамдардың қысқаша сипаттамасы.
DLL мен жұмыс жасайтын екі тәсілді қарастырайық:
1 тәсіл. DLL-ді бағдарламаға жалғау. Бұл DLL- мен жұмыс жасаудың қарапайым тәсілі, бірақ оның бір қателігі бар. Егер кітапхана табылмаса, онда бағдарлама жүктелмейді, ол тек қана Dll ді таба алмайм деген қателікті шығарады. C:\Windows\System және т.б папкаларында, ағымдағы папкадан, түпкі папкадан іздеу жүргізіледі.
Қабылдаудың жалпы формасы:
implementation ...
function FunctionName(Par1: Par1Type; Par2: Par2Type; ...): ReturnType; stdcall; external 'DLLNAME.DLL' name 'FunctionName' index FuncIndex;
// Ал егерде бұл функция емес процедура болған жағдайда.
procedure ProcedureName(Par1: Par1Type; Par2: Par2Type; ...); stdcall; external 'DLLNAME.DLL' name 'ProcedureName' index ProcIndex;
FunctionName(ProcedureName) – бағдарламада қолданылатын функция немесе процедура аты.
Par1, Par2 ... – функцияда (процедурада) қолданылатын параметрлер тізімі.
ReturnType - тек қана функцияға арналған қайтарылатын мәндер.
stdcall - DLL дің өзінде қолданылатын директиваға сәйкес келетін директива.
external – бұл директива функцияның немесе процедураның (берілген жағдайдаDllName.Dll) қай DLL ден импортталатының көрсетеді.
Name – керекті Dll ден импортталатын функцияның нақты атын көрсететін директива. Бұл директива міндетті болып саналмайды.
index – бұл тағыда міндетті емес директива. Бұл директива функцияның (процедураның) Dll дегі реттік номерін көрсетеді.
2 тәсіл. DLL-дің динамикалық жүктелуі. Бұл әдіс қиындығына қарамастан, бұл әдіс кең қолданылады. Бұл әдіс алдыңғы тәсілдің қателіктерін өндеген, бірақта бұл нұсқаға арналған код ауданы өлшемі таң қаларлықтай. Бұл тәсілдің қиындығы Dll ден импортталатын функция Dll жүктелгенде және жадыда орналасқанда қол жетімді болады.
LoadLibrary(LibFileName: PChar) – көрсетілген
Dll ден жадыға жүктеу. Операцияның
сәтті аяқталғанында осы
GetProcAddress(Module: THandle; ProcName: PChar) – экспортталатын кітапхананың функциясының адрессін оқиды. Функцияның сәтті аяқталғанында жүктелген DLL дегі дескрипторды(TFarProc) қайтарады.
FreeLibrary(LibModule: THandle) – бұл модульді жарамсыз қылады және онымен байланысқан жадыны босатады. Бұл функцияны шақырғаннан кейін кітапхана функцияларын қол жетімсіз болады.
Енді негізгі маңыздылары, мысал:
Мысал:
DLL - ді бағдарламамен байланыстыру
{... Мұнда файл тақырыпшасы болады және TForm1 формасын және оның көшірмесін Form1 анықтау }
implementation
{сыртқы кітапханалық функцияны анықтаймыз}
function GetSimpleText(LangRus: Boolean): PChar; stdcall; external 'MYDLL.DLL';
procedure Button1Click(Sender: TObject);
begin
{және оны пайдаланамыз}
ShowMessage(StrPas(GetSimpleTe
ShowMessage(StrPas(
{ShowMessage – көрсетілген жазбамен диалогтық терезені көрсетеді; StrPas - PChar жолын string қа өзгертеді}
end;
енді екінші тәсілге мысал келтірейік:
Мысал:
Dll ді динамикалық жүктеу.
{... Мұнда файл тақырыпшасы болады және TForm1 формасын және оның көшірмесін Form1 анықтау }
var
Form1: TForm1;
GetSimpleText: function(LangRus: Boolean): PChar; LibHandle: THandle;
procedure Button1Click(Sender: TObject);
begin
{функция адрессін "кірлерден" "тазалаймыз"}
@GetSimpleText := nil;
{Кітапхананы жүктеуге тырысамыз}
LibHandle := LoadLibrary('MYDLL.DLL');
{Егер бәрі жақсы болса}
if LibHandle >= 32 then begin
{...онда кітапханадағы функция адрессін алуға тырысамыз}
@GetSimpleText := GetProcAddress(LibHandle,'
{Ал егер де осы жерде де бәрі жақсы болса}
if @GetSimpleText <> nil then
{...онда осы функцияны шақырамыз және шешімдерін көрсетеміз}
ShowMessage(StrPas(
end;
{Және де жадыны босатып, DLL ді жүктеуді ұмытпаңыз}
FreeLibrary(LibHandle);
end;
Бірінші тәсілдің екінші тәсілден айырмашылығы айдан анық көрініп тұр деп ойлаймын... Енді кітапхананың өзін қарастырайық.
3 мысал. MyDll.dpr проектісінің түпнұсқасы:
library mydll;
uses SysUtils, Classes;
{Определяем функцию как stdcall}
function GetSimpleText(LangRus: Boolean): PChar; stdcall;
begin
if LangRus then Result := PChar('Здравствуй, мир!')
else Result := PChar('Hello, world!');
end;
exports GetSimpleText;
begin end.
Delphi ортасында DLL құрудың
ең қарапайым мысалын
Бұл есептің DLL-дегі коды:
library MyFirstDLL;
uses
SysUtils,
dialogs,
Classes;
{$R *.res}
Procedure FirstCall; stdcall; export;
//Stdcall – При этом операторе параметры помещаются в стек
//справа налево, и выравниваются на стандартное значение
//Экспорт в принципе можно опустить, используется для уточнения
//экспорта процедуры или функции.
Begin
ShowMessage('Моя первая
//Вызываем сообщение на экран
End;
Procedure DoubleCall; stdcall; export;
Begin
ShowMessage('Моя вторая
//Вызываем сообщение на экран
End;
Exports FirstCall, DoubleCall;
//В Exports содержится список экспортируемых элементов.
//Которые в дальнейшем
будут импортироваться какой-
begin
end.
Ал енді бұл есептің Delphi – де шақырғандағы коды төмендегідей:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
LibHandle: HModule; //Ссылка на модуль библиотеки
FirstCall: procedure; stdcall;
//Имена наших процедур лежащих в библиотеке.
DoubleCall: procedure; stdcall;
implementation
{$R *.dfm}
Procedure LoadMyLibrary(FileName: String);
Begin
LibHandle:= LoadLibrary(PChar(FileName));
//Загружаем библиотеку!
// Внимание ! PChar для версий ниже 2009 Delphi
If LibHandle = 0 then begin
MessageBox(0,'Невозможно
Exit;
End;
FirstCall:= GetProcAddress(LibHandle,'
//Получаем указатель на объект
//1-ий параметр ссылка на модуль библиотеки
//2-ой параметр имя объекта в dll
DoubleCall:= GetProcAddress(LibHandle,'
If @FirstCall = nil then begin
//Проверяем на наличие этой функции в библиотеке.
MessageBox(0,'Невозможно
Exit;
End;
If @DoubleCall = nil then begin
//Проверяем на наличие этой функции в библиотеке.
MessageBox(0,'Невозможно
Exit;
End; End;
procedure TForm1.FormCreate(Sender: TObject);
begin
LoadMyLibrary('MyFirstDLL.dll'
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
FirstCall; // Имя процедуры, которая находится в dll
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DoubleCall; // Имя процедуры, которая находится в dll
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeLibrary(LibHandle);
//Выгружаем библиотеку из памяти.
end;
end.
Жоғарыда көрсетілген программа кодын түсіндіріп кететін болсақ, бұнда екі процедура қолданылған. Бұл екі процедураны Delphi ортасында жаңа жоба ашып, форма бетіне екі Button пернесін қойып сол екі перне арқылы осы екі процедураны шақырамыз. Құрылған DLL-ді компилятор таба алмаған жағдайда бізге хабар береді. Ал тапқаннан кейін DLL-дегі жазған процедураларымызды шығарады. 3.1-суретте көрсетілген.
3.1-сурет. Каталогқа сақталған құрылған DLL
3.2-сурет. DLL – дегі алғашқы процедураны Delphi - де шақыру
3.3-сурет. DLL – дегі екінші процедураны Delphi - де шақыру
3.4-сурет. Delphi ортасында қажетті DLL – ді таппаған жағдайда қате шығарады
DLL негізінен модульге ұқсас болып келеді, олардың кодтары бағдарламаны еске түсіреді. Мұнда таң қалатын ештене жоқ, себебі DLL тек бағдарламаның әртүрлілігі. Ол басқа бағдарламалармен жұмыс жасау үшін кодты ұсынады. Осы мысалда қарапайым DLL жалғыз BeepMe функциясымен қарастырылған. Бұл функцияны шақырған кезде компьютер тек қана дыбыстық сигнал береді.
library beeper;
uses
SysUtils,Classes,
Windows;
{$R *.res}
procedure BeepMe; stdcall;
begin
MessageBeep (0);
end;
Exports
BeepMe index 1 name 'BeepMe';
begin
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,beepdll;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
BeepMe;
end;
end.
3.5-сурет. Beeper.dll кітапханасын Delphi – де шақыру
Өзіңіздің проектіңізді өзіңіз құрған каталогқа MyDLL деген атпен сақтаңыз. Осыдан кейін жоғарыда көрсетілген мәтінде кітапхана аты автоматы түрде MyDLL деген атпен алмасады. Біз осы кітапханаға функция енгізгіміз келсе, мысалы, үш шынайы санның ортақ мәнін шығаратын функция енгізейік. Оған Average деген ат берейік. Кітапхананың модуль мәтініне бұл функцияның келесідей түрін қосыңыз:
library MyDLL;
uses
SysUtils,
Classes;
Function Average(A,B,C:real):real; export; stdcall;
begin
Average:=(A+B+C)/3;
end;
exports
Average;
end.
{$R *.res}
begin
end.
Функцияның тақырыпшасынан кейін екі кілттік сөз - export және stdcall жазылғандығына назар аударыңыз. Олардың біріншісі функцияның сыртқы қолдануға арналғандығын білдіреді, демек оны пайдаланушы кітапханадан шақыра алады. Компилятор бұл функция үшін far шақыру моделін қолданады. Stdcall кілттік сөзі функция шақырған кезде параметрді берудің стандарты келісімін қолданатының білдіреді.
Exports сөзінен кейін экспортталатын функциялар мен процедуралар тізіледі. Exports тізімін кітапханада іздеуді жеңілдететін көрсеткіш ретінде қарастыруға болады. Кітапхана модулі мәтініне өзіміздің функциямызды енгізе отырып, Project |Build командасын орындаңыз. Нәтижесінде MyDLL.dll файлды кітапхана құрылады. Енді оны біз бағдарламаларда қолдана аламыз. Осы функцияны тексеретін қосымша құрыңыз. Жаңа проект ашып, формаға пайдаланушы сан енгізетін үш Edit компонентін орналастырыңыз, нәтижені көрсету үшін Label компонентін қойыңыз және бір перне қойыңыз. Бұл пернені басқанда Label көмпоненті жолында енгізілген сандардың орташа мәні көрсетіледі. Сіздің мәтіңіздің implementation бөлімі келесідей түрде болуы керек: