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

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

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

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

Файлы: 1 файл

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

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

Бұл процедураны қосымшаның параметрінен шақырған кезде қосымша классының экземплярын көрсету керек:

procedure ShowDemoForm(AOwner: TComponent); external 'DataCtrl.dll';

procedure TMainForm.BitBtnlClick(Sender: TObject); 

begin

ShowDemoForm(Application);

end;

Берілген жағдайда динамикалық кітапханадағы форма операциялық жүйеде жеке тапсырма ретінде қаралатындыына назар аударыңыз.

 

2. DELPHI ПРОГРАММАЛАУ  ОРТАСЫНДА DLL ДИНАМИКАЛЫҚ КІТАПХАНАЛАРЫН ҚҰРУ ЖӘНЕ ҚОЛДАНУ

 

2.1 DLL проектісі

 

 

Delphi репозиториясында динамикалық  кітапханаларды құру үшін арнайы  шаблон қолданылады. Оның белгісі New Репозитория бетінде орналасқан DLL Wizard. Проектінің қарапайым қосымшадан айырмашылығы DLL проектісі тек қана бір файлдан тұрады. Одан кейін оған жеке модульдер мен формалар қосуға болады. 2.1-суретте көрсетілген.

 

 

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 бөлімінде сол сақталған атпен автоматты түрде кітапхана құрады.

 

 

2.2 Динамикалық қосылатын кітапханалардың іске асуы

 

 

DLL жұмысқа дайын процедуралардан, функциялардан немесе ресурстардан  тұратын орындалатын модуль түрінде  іске асады. Бағдарламаушының көзімен қарағанда DLL және Object Pascal үшін қарапайым модульдер арасында көптеген сәйкестіктер бар. Кітапханаларда, модульдерде қосымша бағдарлама болып келеді. Олар тек бағдарламаушыны өзінің кодын жазуға жеңілдету үшін пайдаланатын болып шығады. Бірақ та принципті ерекшеліктері де кездеседі. Олардың негізгісі болып DLL - дің бағдарламаға енгізулер, константалар және типтер енгізу жағдайында болмауын жатқызуға болады. Себебі DLL құрушылары типизирлі бағдарламалау тілдерін қолдана алмайды. Ол тілдерге мысалға ассемблерді алуға болады. Сонында DLL бағдарламаға қазіргі кезде бағдарламаушыға керекті класстарды экспорттай алмайды. Осы жағдай үшін пакеттер қолданылады.

Object Pascal - да DLL - ді құру үшін Library деген сөз енгізілген. Бұл сөзбен кітапхана мәтіні басталуы керек. Library деген сөзден дұрыс идендификатор тұрады, бірақ модульді шақырудан айырмашылығы ол файл атымен сәйкес келмеуі керек: DLL аты идентификатормен емес DLL файл атымен анықталады.

DLL мәтінінің құрылымы  қарапайым бағдарламаның құрылымын  шектеулермен қайталайды. Ол шектеулерге DLL дегі орындалатын операторлар бөлімі инициалданатын модуль бөлімі орындайтын рөлді орындауы жатады. Модуль бөлімінің операторлары жадыға кітапхананы жүктеген кезде, 2.3 – суретте көрсетілгендей бір рет қана орындалады.

 

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;

 

 

2.3 Интерфейстік модуль

 

 

DLL- қосымша бағдарламаларды  шақырған кезде көптеген жағдайда  жазбалардың типтеріне алғашқы мысалдағы Tcomplex типі секілді құрылымдық параметр беру міндетті болады. DLL типтерді экспорттай алмайтындықтан бұл типтерді шақырылған бағдарламада хабарлау керек. Егер сіз өздеріңіздің бағдарламаңызда сол немесе басқа 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 кітапханасына дәл осындай интерфейспен қамтамассыздандырады.

 

 

2.4 DLL құру барысында туындайтын шектеу жағдайлар

 

 

Delphi де құрылған DLL-дегі туындайтын шектеулі жағдайлар барлық қосымшалардың іске асуын тоқтатуға әкеп соғады. Бұл жағдайлар DLL-дің ішінде өнделмеген болған жағдайда. Сондықтан DLL-ді құрған кезде барлық мүмкін болатын қателіктерді қарастырып кеткен жөн. Импортталатын функцияның жол немесе сан түріндегі іске асқан шешімін қайтаруды ұсынуға болады және де керек болған жағдайда бағдарламадағы шектеулі жағдайларды қайтадан шақыруға болады.

DLL-дегі код:

function MyFunc : string;

begin

try

{собственно код функции}

except

on EResult: Exception do

Result:=Format(DllErrorViewingTable,

[EResult.Message]);

else

Result := Format(DllErrorViewingTable,

['Unknown error']);

end;

end;

Бағдарламадағы код:

StrResult:=MyFunc;

if StrResult<>'' then

raise Exception.Create(StrResult);

 

2.5 DLL -ді қолдану аймақтары

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