Динамикалық кітапханалар

Автор работы: Пользователь скрыл имя, 06 Апреля 2014 в 10:25, курсовая работа

Описание работы

Бағдарламалау технологиясының дамуына байланысты көптеген адамдар өздерінің бағдарламаларының мүмкіндіктерін жоғарлату қателіктерімен соқтығысып жатады. Осы менің курстық жұмысым осы сұраққа арналған, яғни Borland Delphi тілінде DLL – ді бағдарламауға. Сонымен қоса, DLL кітапханаларын пайдалану туралы сұрақтарды қарастырғанда, біз басқа DLL – дан импорттауды да қарастырып кетеміз.

Файлы: 1 файл

курсовой исрп.doc

— 586.00 Кб (Скачать файл)

 

 

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 ден жадыға жүктеу. Операцияның  сәтті аяқталғанында осы кітапхананың  дескрипторы (THandle) қайтарылады.

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(GetSimpleText(True)));

ShowMessage(StrPas(GetSimpleText(False)));

{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,'GetSimpleText');

{Ал егер де осы жерде де бәрі жақсы болса}

if @GetSimpleText <> nil then

{...онда осы функцияны шақырамыз және шешімдерін көрсетеміз}

ShowMessage(StrPas(GetSimpleText(True)));

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.

 

3. ТӘЖІРИБЕЛІК  БӨЛІМ

 

3.1 DELPHI программалау ортасының DLL құруға келтірілген мысалдар

 

 

1 – ЕСЕП

 

 

Delphi ортасында DLL құрудың  ең қарапайым мысалын қарастырайық. Бұл мысалда менің алғашқы  құрған динамикалық кітапхана  аты MyFirstDLL. Бұл кітапханада екі  қарапайым процедура жазылған. Ол FirstCall, DoubleCall процедуралары. Бұл процедураларды DLL – де құрып, оны Delphi – де екі перненің көмегімен шақырамыз. Динамикалық кітапханаларды Delphi – де қалай құратынын жоғарыда айтып кеттік.

Бұл есептің DLL-дегі коды:

library MyFirstDLL;

uses

SysUtils,

dialogs,

Classes;

{$R *.res}

Procedure FirstCall; stdcall; export;

//Stdcall – При этом операторе  параметры помещаются в стек 

//справа налево, и выравниваются  на стандартное значение

//Экспорт в принципе  можно опустить, используется для  уточнения

//экспорта процедуры или  функции.

Begin

ShowMessage('Моя первая процедура  в dll');

//Вызываем сообщение на  экран

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,'Невозможно загрузить библиотеку',0,0);

Exit;

End;

FirstCall:= GetProcAddress(LibHandle,'FirstCall');

//Получаем указатель на  объект

//1-ий параметр ссылка  на модуль библиотеки

//2-ой параметр имя объекта  в dll

DoubleCall:= GetProcAddress(LibHandle,'DoubleCall');

If @FirstCall = nil then begin

//Проверяем на наличие  этой функции в библиотеке.

MessageBox(0,'Невозможно загрузить  библиотеку',0,0);

Exit;

End;

If @DoubleCall = nil then begin

//Проверяем на наличие  этой функции в библиотеке.

MessageBox(0,'Невозможно загрузить  библиотеку',0,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 – ді таппаған жағдайда қате шығарады

 

2 – ЕСЕП

 

 

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 – де шақыру

 

 

3 – ЕСЕП

 

 

Өзіңіздің проектіңізді өзіңіз құрған каталогқа 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 бөлімі келесідей түрде болуы керек:

Информация о работе Динамикалық кітапханалар