Күрделі delphi DLL құру мысалдары. Delphi қолданбасында DLL жүктелуде

Құрметті әріптестер!

Бұл мақалада мен сұрақтарға жауап беруге тырысамын: Бұл не DLL? Ол не үшін? Және қалай құру және пайдалану DLLкөмегімен Delphi.

DLL дегеніміз не?

Динамикалық сілтеме кітапханасынемесе қысқаша DLLбасқа бағдарламаларда пайдалануға арналған деректер немесе функциялар жиынын қамтитын кітапхана.

Қолдану аймақтары:

  • Ресурстарды сақтау: белгішелер, дыбыстар, курсорлар және т.б. Біз ресурстарды бір кітапханаға біріктіру арқылы орындалатын файлдардың көлемін үнемдейміз.
  • Бағдарламаның жеке модульдерін және интерфейс формаларын орналастыру. Біз қосымшаны ішінара жаңарту мүмкіндігін аламыз, ал динамикалық қосылым арқылы негізгі бағдарламаны қайта іске қоспай-ақ модульдерді жаңартуға болады.
  • Плагиндер ретінде пайдаланыңыз (PlugIn). Біз негізгі бағдарлама кодын қайта жазбастан қосымшаның функционалдығын кеңейту мүмкіндігін береміз.
  • Кітапхана қай тілде жазылғанына қарамастан әртүрлі бағдарламалау тілдерінде қолданылуы мүмкін.

Жеке DLL жасау.

Кітапхана жасау үшін мәзірге өтіңіз Файл -> Басқажәне таңдаңыз Delphi жобалары -> Динамикалық сілтеме кітапханасы.
Кітапхана құру үлгісі бар код мәтіні ашылады:

Кітапхана жобасы 1; System.SysUtils, System.Classes пайдаланады; ($R *.res) бастаудың соңы.

Ресурстарды орналастыру

Кітапханаға белгішені қосамыз, оны кейінірек негізгі бағдарламада қолданамыз.
Жобаға ресурстарды қалай қосу керектігі мақалада егжей-тегжейлі сипатталған.

«Бағдарлама туралы» пішінін қосамыз.
басыңыз Файл -> Жаңа -> VCL пішіні. Мәтінді және «OK» түймесін қосамыз:

Стандартты көрсететін функцияны қосамыз MessageBoxсұрақпен, «Иә», «Жоқ» түймелерімен және пішіндегі нәтижемен Раснемесе Жалған.

YesNoDlg функциясы (const Сұрақ: PChar): логикалық; stdcall; begin Нәтиже:= (MessageBox(0, сұрақ, "Растау", MB_YESNO + MB_ICONQUESTION) = ID_YES); Соңы;

Негізгі сөзге назар аударыңыз stdcall. Ол функцияларды шақыру кезінде параметрлер мен нәтижелердің қалай берілетінін дәл анықтайды. Толығырақ Қоңырау шалу келісімі вики бетінде оқи аласыз.

Сондай-ақ біз негізгі бағдарлама үшін плагин ретінде пайдаланылатын процедураны қосамыз. Бұл біз жасаған терезені ашу үшін бағдарламаның негізгі мәзіріне «Бағдарлама туралы» түймешігін қосады.
Процедураның коды:

Procedure Plugin(Пішін: TForm); stdcall; var i: integer; mi: TMenuItem; start for i:= 0 to Form.ComponentCount - 1 басталады, егер (Form.Components[i].ClassName = "TMenuItem") және (Form.Components[i].Name = "miHelp"), содан кейін басталады mi:= TMenuItem .Create(Form.Components[i]); mi.Caption:= "Бағдарлама туралы"; mi.OnClick:= fmAbout.onAboutButtonClick; TMenuItem(Form.Components[i]).Add(mi); Шығу; Соңы; Соңы; Соңы;

Процедураға параметр ретінде программаның формасы беріледі. « деп аталатын мәзір элементінің бар-жоғын тексереміз. miHelp«және мәзір табылса, оған біздің түймені қосыңыз.

Енді кітапханамыздан қандай функциялар мен процедураларды қолдануға болатынын көрсетеміз.
Жолды қосамыз:

PlugIn, YesNoDlg экспорттауы;

Функцияны құрастырайық Жоба -> Құрунемесе жылдам пернені пайдалану Shift+F9.
Егер кодта қателер болмаса, жоба қалтасында кеңейтімі бар файл пайда болуы керек DLL.

Енді кітапханамызды пайдаланатын қосымшаны құруға көшейік.

Қолданбада пішін жасайық Негізгіонда біз келесі түймелермен құрамдас қосамыз: Бағдарлама -> Шығу және Анықтама. Соңғысы үшін атауды белгілейік - miHelp:

Пішін кодына көшейік.

Кітапхананың функциялары DLLекі жолмен қосылуы мүмкін:
Статикалық— бағдарлама іске қосылғанда кітапхана қосылады. Кітапхана немесе функция атауы табылмаса, бағдарлама қате жасайды және іске қосылмайды.
Динамикалық— кітапхана функцияны шақыру алдында немесе белгілі бір оқиғаға бірден қосылады.

Статикалық қосылым әдісін қарастырайық:

TfmMain түрі = class(TForm) MainMenu: TMainMenu; miProgram: TMenuItem; miExit: TMenuItem; miHelp: TMenuItem; процедурасы FormCreate(Жіберуші: TObject); miExitClick процедурасы(Жіберуші: TObject); жеке қоғамдық мақсат; процедура PlugIn(Форма: TForm); stdcall; сыртқы "SampleDLL.dll"; var...

Негізгі сөз сыртқыбұл функцияның сыртқы кітапханадан қосылғанын көрсетеді.

Оқиға үшін onCreateпішін, процедура шақыруын қосыңыз Плагин:

TfmMain.FormCreate процедурасы(Жіберуші: TObject); PlugIn(Өздігінен) бастау; Соңы;

Параметр ретінде Пішінбіз ағымдағы пішінді процедураға береміз (кілт сөз Өздігінен).

Бағдарламаны іске қосқан кезде бізде негізгі мәзірдің «Анықтама» бөлімінде «Бағдарлама туралы» тармағы болуы керек.

Динамикалық қосылу әдісіне көшейік.

Бізге үш функция қажет болады WinApi:

Кітапхананы жүктеңіз
Кітапхананы компьютер жадына жүктейді. Нәтижесінде жадтағы кітапханаға көрсеткішті қайтарады. Қате болған жағдайда ол 0 қайтарады.

LoadLibrary(lpLibFileName: LPCWSTR): HMODULE;

lpLibFileName— Кітапхана файлының аты.

GetProcAddress
Кітапханадағы функцияны аты бойынша табыңыз. Нәтиже функция көрсеткіші болады. Егер функция табылмаса, ол қайтарылады нөл.

GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC;

hModule
lpProcName— Функция атауы.

Тегін кітапхана
Кітапхананы компьютер жадынан босатады. Нәтиже сәтті болған жағдайда True, қате болған жағдайда False болады.

FreeLibrary(hLibModule: HMODULE): BOOL;

hLibModule— Жүктелген кітапханаға көрсеткіш.

Енді динамикалық әдісті қолдана отырып, біз ресурстарды, белгішені аламыз және «Шығу» түймесіне функционалдық шақыруды қосамыз ИәЖоқDlgбағдарламаның жабылғанын растау үшін.
Бір onCreate оқиғасына келесі кодты қосыңыз:

TfmMain.FormCreate процедурасы(Жіберуші: TObject); var DLLHandle: THandle; PlugIn(Өздігінен) бастау; DLLHandle:= LoadLibrary("SampleDLL.dll"); егер DLLHandle = 0 болса Exception.Create ("SampleDLL" кітапханасын қосу мүмкін емес!"); Self.Icon.LoadFromResourceName(DLLHandle, "my_icon") әрекетін көріңіз; соңында FreeLibrary(DLLHandle); Соңы; Соңы;

Және оқиға үшін onClick«Шығу» мәзір элементі:

TfmMain.miExitClick процедурасы(Жіберуші: TObject); var DLLHandle: THandle; Dlg: function(const Сұрақ: PChar): логикалық; stdcall; begin DLLHandle:= LoadLibrary("SampleDLL.dll"); егер DLLHandle = 0 болса Exception.Create ("SampleDLL" кітапханасын қосу мүмкін емес!"); @Dlg:= GetProcAddress(DLLHandle, "YesNoDlg"); if Assigned(@Dlg) болмаса, Exception.Create ("YesNoDlg" деп аталатын функция "SampleDLL" кітапханасында табылмады!"); егер Dlg("Бағдарламадан шығу керек пе?"), онда Жабу; соңында FreeLibrary(DLLHandle); Соңы; Соңы;

Егер сіз бәрін дұрыс жазған болсаңыз, бағдарламаны іске қосқаннан кейін пішін белгішесі өзгеруі керек, «Бағдарлама туралы» түймесі қосылуы керек, оны басқан кезде пішін көрсетіледі. туралыжәне шығу түймесін басқан кезде, бағдарлама растауды сұрайды: «Бағдарламадан шығу керек пе?»

Мүмкіндіктерді пайдаланудың осы шағын мысалы сізге пайдалы деп үміттенемін. DLLкітапханалар.
Жоба көздерін жүктеп алуға болады.

Кем дегенде, ДК пайдаланушыларының көпшілігі DLL не екенін біледі, әсіресе бағдарламашылар, егер сіз осы мақаланы оқып жатқан болсаңыз. Бұл мақалада мен DLL-ге қатысты барлық жалпы сұрақтарды қарастыруға тырысамын.

Біз нақты нені қарастырамыз:

  1. Әдеттегідей, «Hello World» аймағынан біз бірінші DLL-ді жасаймыз.
  2. Осы DLL функцияларын өз бағдарламаларымыздан қалай пайдалану керектігін үйренейік.
  3. Арнайы DLL экспорттайтын функцияларды көру жолын үйренейік.
  4. Басқа нәрсе болуы мүмкін....

DLL құру процесі

Ең қарапайым нәрседен бастайық - «Hello World» хабарын көрсететін бір ғана функцияны қамтитын бірінші DLL-ді жазу.

  1. Delphi-ді іске қосамыз (мен Delphi 6-ны қолданамын).
  2. Келесі: Файл -> Жаңа -> Басқа

Жаңа қойындысында DLL шебері нысанын екі рет басыңыз. Жаңа жоба ашылады. Оны MyFirstDLL атымен сақтаңыз, мысалы.

Таза модульде келесідей нәрсе бар:

MyFirstDLL кітапханасы; SysUtils, Classes пайдаланады; ($R *.res) бастаудың соңы.

Енді Dialogs модулінен ShowMessage() шақыратын бір ғана функцияны жазайық. Сондықтан процедураны бастамас бұрын Диалогтар модулін Қолдану бөліміне қосамыз. Сіз шамамен не алуыңыз керек:

MyFirstDLL кітапханасы; Диалогтарды пайдаланады; MyFirstFunc процедурасы; stdcall; ShowMessage бастау («Сәлем әлем»); Соңы; MyFirstFunc экспорттайды; бастау аяғы.

Көріп отырғаныңыздай, мұнда өте күрделі ештеңе жоқ. Жалғыз айтарым, функцияларды аты бойынша да, индексі (саны) бойынша да шақыруға болады, ол үшін келесідей жазу керек:

MyFirstFunc 1 индексін экспорттайды;

Егер осы кодта бірдеңе түсініксіз болса, алдымен оны өзіңіз анықтап көріңіз. Менің ойымша, бұл мәселеде ешқандай проблема болмайды... Бірақ егер бірдеңе болса, онда форум.! Әрі қарай, бұл (MyFirstFunc) функциясын басқа жобалардан қалай пайдалануға болады?

DLL функцияларын пайдалану

Алғашқы қадам жасалды, бұл уақыт мәселесі... Бұл функцияны қалай пайдалана аламыз?

Кем дегенде екі жүктеу әдісі бар:

  1. Статикалық
  2. Динамикалық

Екінші әдіс жақсырақ, өйткені жүктеу кезінде біз болып жатқан барлық нәрсені бақылай аламыз және жүктеу кезінде пайда болатын барлық қателерді түзете аламыз. Бірақ алдымен бірінші әдісті қарастырайық:

Біз жаңа жоба жасаймыз, пішінге бір түймені тастаймыз және осы түйменің OnClick оқиғасында келесіні жазамыз:

TForm1.Button1Click процедурасы(Жіберуші: TObject); MyProc(); Соңы;

Бірақ бұл бәрі емес! Жобаның іске асыру бөлімінде мынаны жазыңыз:

Іске асыру процедурасы MyProc(); stdcall; сыртқы "MyFirstDLL.dll" атауы "MyFirstFunc";

Дайын! Жобаны құрастырыңыз және түймені басыңыз! Егер сіздің хабарламаңыз пайда болса, бәрі жақсы!

Енді динамикалық жүктеу әдісін қарастырайық. Бұл әдіс үшін LoadLibrary() функциясын пайдаланыңыз, ал соңында босату үшін FreeLibrary() пайдаланыңыз.

Мысалға қараңыз:

TForm1.Button1Click процедурасы(Жіберуші: TObject); TMyFunc түрі = процедура; var DLLInstance: THandle; MyFunc: TMyFunc; begin DLLInstance:= LoadLibrary(PChar("MyFirstDLL.dll")); егер (DLLInstance = 0) болса, MessageDlg ("DLL жүктеу мүмкін емес", mtError, , 0) бастаңыз; Шығу; Соңы; @MyFunc көріңіз:= GetProcAddress(DLLInstance, "MyFirstFunc"); if Assigned(@MyFunc) then MyFunc() else MessageDlg("Қажетті процедура табылмады!.", mtError, , 0); соңында FreeLibrary(DLLInstance); Соңы; Соңы;

DLL файлын LoadLibrary() функциясымен сәтті жүктегеннен кейін GetProcAddress() көмегімен функциямыздың мекенжайын табамыз, сол кезде DLL-ден процедурамызды шақырамыз. Соңында FreeLibrary() функциясын орындау керек. Мұның маңыздылығы сонша, мен сәтті жүктеп алғаннан кейін барлық кодты FreeLibrary() дейін try finally блогына қостым. Бұл try except блогының ішіндегі әрекеттерді орындау кезінде күтпеген ерекше жағдай орын алса да FreeLibrary орындалатынын қамтамасыз етеді.

Мәселе мынада, LoadLibrary және FreeLibrary бағдарламасына сәтті қоңыраулар жұптастырылуы керек. Және сол себепті. Жүйе процесс арқылы жүктелген әрбір кітапхана үшін LoadLibrary бағдарламасына әрбір сәтті шақыру кезінде 1-ге артатын ішкі есептегішті сақтайды. Сәйкесінше, FreeLibrary орындалғанда, ол бұл есептегішті азайтады, ал егер ол нөлге тең болса, бұл кітапхана бұл процеске енді қажет емес және оны жадтан қауіпсіз жоюға болады дегенді білдіреді.

Егер жұптастыру ережесі сақталмаса, бұл кітапхананың жадтан мерзімінен бұрын босатылуына (егер қосымша FreeLibrary болса) немесе оның сол жерде «жабысып қалуына» (егер FreeLibrary жеткіліксіз болса) әкелуі мүмкін.

Осы ережені ұстанатын болсаңыз, LoadLibrary / FreeLibrary қоңырауларының ықтимал кірістіру мүмкіндігі туралы алаңдамайсыз.

Арнайы DLL функцияларын қарау

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

Сонымен, жаңа жоба жасаңыз, пішінге ListBox тастаңыз, онда біз функциялардың атауларын көрсетеміз.

Мұнда бүкіл жоба:

Unit Unit1; интерфейс Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls пайдаланады; TForm1 түрі = сынып(TForm) lb: TListBox; процедурасы FormCreate(Жіберуші: TObject); private ( Private declarations ) cmdline: String; ImageBase: DWord; DosHeader: PImageDosHeader; PeHeader: PImageNtHeaders; PExport: PImageExportDirectory; pname:PDWord; аты: PChar; жария (Қоғамдық декларациялар) аяқталуы; var Form1: TForm1; іске асыру ($R *.dfm) процедурасы TForm1.FormCreate(Sender: TObject); FatalOsError процедурасы; Start ShowMessage(SysErrorMessage(GetLastError())); Тоқтату; Соңы; Var i: Integer; бастаңыз, егер (ParamCount() IMAGE_DOS_SIGNATURE), содан кейін FatalOsError; PEHeader:= PImageNtHeaders(DWord(ImageBase) + DWord(DosHeader^._lfanew)); егер (PEHeader^.Сигнатура IMAGE_NT_SIGNATURE), онда FatalOsError; PExport:= PImageExportDirectory(ImageBase + DWord(PEHeader^.OptionalHeader.DataDirectory.VirtualAddress)); pname:= PDWord(ImageBase + DWord(PExport^.AddressOfNames)); i:= 0 үшін PExport^.NumberOfNames - 1 басталатын атау:= PChar(PDWord(DWord(ImageBase) + PDword(pname)^)); lb.Items.Add(аты); inc(pname); Соңы; соңында FreeLibrary(ImageBase); Соңы; Application.ShowMainForm қоспағанда:= False; Қолдану. Аяқтау; Соңы; Соңы; Соңы.

Егер сіз кодты өзіңіз анықтағыңыз келсе және бірдеңе сізге көмектеспесе, онда біздің форум сізге міндетті түрде көмектеседі, кіріңіз!

Біз Viewer-ді барлық DLL файлдарына қосамыз

Бізде функциясы бар дайын DLL бар және бізде функцияны қарау құралы бар. Әрі қарай жұмыс істеуге ыңғайлы болу үшін кейбір функционалдылықты қосу қалады. Мұны істейік... Explorer бағдарламасында кез келген қалтаны ашыңыз. Құралдар -> Қалта параметрлері тармағына өтіңіз... «Файл түрлері» қойындысына өтіңіз. Біз тізімнен DLL пішімін іздейміз. Егер мұндай нәрсе болмаса, «Жасау» түймесін басып, «Кеңейтім» өрісіне DLL жазыңыз. OK түймесін басыңыз. Біз жасаған типті табамыз - DLL. Оны таңдап, «Қосымша» түймесін басыңыз. Келесі «Жасау», «Әрекеттер» өрісінде контекстік мәзірде не көрсетілетінін жазамыз, мысалы, DLL Viewer. Шолу арқылы біз өз бағдарламамызды іздейміз.

Бәрі дайын!

Енді DLL пішіміндегі файлды тінтуірдің оң жақ түймешігімен басқан кезде, мәзірде біздің DLL қарау құралы пайда болады. Оны таңдап, барлық функцияларды көріңіз!

Барлығы осы, назарларыңызға рахмет!

Назарларыңызға мен талқылауды жалғастыратын ақпараттық бюллетеньдің кезекті санын ұсынамын
Borland Delphi-де DLL-ді әзірлеу және пайдалану мәселелері. Жаңа жазылушылар үшін мен сізге хабарлаймын,
пошталық мұрағаттың №13 шығарылымындағы мақаланың бірінші бөлігін қарауға болатынын.
Маған хат жазып, жауап алмаған жандардан кешірім сұраймын. Мен мұны жақын арада түзетуге тырысамын.
Ендеше жалғастырайық.

Динамикалық кітапханада орналасқан кез келген процедураны немесе функцияны пайдалануды бастамас бұрын,
DLL файлын жедел жадқа жүктеу керек. Кітапхананы жүктеуге болады
екі жолдың бірімен: статикалық жүктеу және динамикалық жүктеу.
Екі әдістің де артықшылықтары мен кемшіліктері бар.
Статикалық жүктеу динамикалық кітапхананың автоматты түрде жүктелетінін білдіреді
оны пайдаланатын қолданба іске қосылғанда. Бұл жүктеу әдісін пайдалану үшін,
неден экспортталатынын сипаттау кезінде сыртқы кілт сөзді пайдалану керек
динамикалық кітапхана функциясы немесе процедурасы. Бағдарлама іске қосылғанда DLL автоматты түрде жүктеледі,
және сіз одан экспортталған кез келген режимдерді сияқты пайдалана аласыз
олар қолданбалы модульдер ішінде сипатталғандай.
Бұл DLL файлында орналастырылған кодты пайдаланудың ең оңай жолы.
Бұл әдістің кемшілігі кітапхана файлы болса
қолданбада сілтеме бар, ол жоқ болса, бағдарлама жүктеуден бас тартады.
Динамикалық әдістің мәні мынада: қолданба іске қосылғанда кітапхананы жүктемейсіз,
және бұл сізге шынымен қажет кезде. Өзіңіз үшін бағалаңыз, өйткені функция сипатталған болса
динамикалық кітапханада, бағдарламаны іске қосудың 10% ғана пайдаланылады, содан кейін мүлдем жоқ
Статикалық жүктеу әдісін пайдаланудың мағынасы жоқ. Бұл жағдайда кітапхананы жадтан шығару
Сіздің бақылауыңызда да жүзеге асырылады. Бұл әдістің тағы бір артықшылығы
DLL файлдарын жүктеу қолданбаның іске қосылу уақытын қысқартуды (анық себептермен) білдіреді.
Бұл әдістің кемшіліктері қандай? Ең бастысы, менің ойымша, пайдалану
Бұл әдіс жоғарыда талқыланған статикалық жүктемеге қарағанда қиынырақ.
Алдымен Windows API LoadLibrary функциясын пайдалану керек.
Экспортталған процедураға немесе функцияға көрсеткішті алу үшін сізге қажет
GetProcAddress функциясын пайдаланыңыз. DLL файлын пайдалануды аяқтағаннан кейін
FreeLibrary арқылы жүктеп алу керек.
DLL файлдарынан жүктелген процедуралар мен функцияларды шақыру.
Процедуралар мен функцияларды шақыру жолы динамикалық кітапхананы қалай жүктегеніңізге байланысты,
онда бұл ішкі бағдарламалар орналасқан.
Статикалық жүктелген DLL файлдарынан функциялар мен процедураларды шақыру өте қарапайым. Бастапқыда қолданбада
экспортталған функцияның (процедураның) сипаттамасын қамтуы керек. Осыдан кейін сіз оларды пайдалана аласыз
олар қолданбалы модульдердің бірінде сипатталғандай.
DLL файлында қамтылған функцияны немесе процедураны импорттау үшін пайдалануыңыз керек
олардың декларациясында сыртқы модификатор. Мысалы, біз жоғарыда қарастырған HelloWorld процедурасы үшін
Қоңырау шалушы қосымшада келесі жол болуы керек:
SayHello процедурасы(AForm: TForm); сыртқы myfirstdll.dll»;
Сыртқы кілт сөз компиляторға процедураны табуға болатынын айтады
динамикалық кітапхана (біздің жағдайда - myfirstdll.dll).
Бұл процедураға шақыру келесідей болады:
...
HelloWorld(өзі);
...
Функциялар мен процедураларды импорттау кезінде олардың атаулары мен интерфейстерін жазғанда әсіресе абай болыңыз!
Мәселе мынада, қосымшаларды құрастыру кезінде нысан атауларының дұрыстығын тексеру жүргізілмейді,
DLL файлынан экспортталған орындалмайды және кез келген функцияны дұрыс сипаттамасаңыз,
онда ерекшелік тек қолданбаның орындалу кезеңінде шығарылады.
DLL ішінен импорттау процедураның (функцияның) аты, реттік нөмірі немесе арқылы жүзеге асырылуы мүмкін
басқа атаумен.
Бірінші жағдайда сіз жай ғана процедураның атын және оны импорттап жатқан кітапхананы жариялайсыз
(біз мұны сәл жоғары қарадық). Реттік нөмір бойынша импорттау дәл осы нөмірді көрсетуді талап етеді:
HelloWorld процедурасы(AForm: TForm); сыртқы myfirstdll.dll индексі 15;
Бұл жағдайда импорттау кезінде процедураға беретін атаумен бірдей болуы міндетті емес
ол үшін DLL файлында көрсетілген. Анау. жоғарыдағы жазбаны білдіреді,
myfirstdll.dll динамикалық кітапханасынан экспортталған процедураны импорттап жатқаныңыз
он бесіншіден және қолданбаңызда бұл процедура SayHello деп аталады.
Егер қандай да бір себептермен жоғарыда сипатталған импорттау әдісін қолданбасаңыз,
бірақ әлі де импортталған функцияның (процедураның) атын өзгерткіңіз келсе, үшінші әдісті қолдануға болады:
CoolProcedure процедурасы; сыртқы myfirstdll.dll атауы "DoSomethingReallyCool";
Мұнда импортталған CoolProcedure процедурасы DoSomethingReallyCool деп аталады.
Динамикалық жүктелген кітапханалардан импортталған процедуралар мен функцияларды шақыру
біз жоғарыда талқылаған әдіске қарағанда біршама күрделірек. Бұл жағдайда сіз мәлімдеуіңіз керек
сіз қолданатын функцияға немесе процедураға көрсеткіш.
HelloWorld процедурасы есіңізде ме? Не істеу керек екенін көрейік
DLL динамикалық жүктелген жағдайда оны орындауға шақыру. Ең алдымен, сіз
осы процедураны сипаттайтын түрін жариялау қажет:
түрі
THelloWorld = процедура(AForm: TForm);
Енді GetProcAddress алу арқылы динамикалық кітапхананы жүктеу керек
процедураға көрсеткіш, орындау үшін осы процедураны шақырыңыз және соңында DLL жадтан шығарыңыз.
Төменде мұны қалай жасауға болатынын көрсететін код берілген:

DLLInstance: THandle ;

HelloWorld:THelloWorld;

БАСТА

(DLL жүктеу)

(көрсеткішті аламыз)

(орындау процедурасын шақыру)

HelloWorld(Self);

(RAM-дан DLL файлын алып тастау)

FreeLibrary(DLLInstance);

Соңы ;

Жоғарыда айтылғандай, DLL-ні статикалық түрде жүктеудің кемшіліктерінің бірі мүмкін еместігі болып табылады
бір немесе бірнеше кітапхана болмаған кезде қолданба жұмысын жалғастыру. Динамикалық жағдайда
Жүктеп алу арқылы сізде мұндай жағдайларды бағдарламалық түрде өңдеуге және бағдарламаны болдырмауға мүмкіндік бар
өздігінен құлап кетті». LoadLibrary және GetProcAddress функцияларымен қайтарылған мәндерге сүйене отырып, сіз
кітапхананың сәтті жүктелгенін және одан қолданба талап ететін процедураның табылғанын анықтау.
Төмендегі код мұны көрсетеді.

процедура TForm1.DynamicLoadBtnClick (Жіберуші: TObject );

түрі

THelloWorld = процедура (AForm: TForm);

DLLInstance: THandle ;

HelloWorld:THelloWorld;

БАСТА

DLLInstance:= LoadLibrary("myfirstdll.dll" );

DLLInstance = 0 болса, бастаңыз

MessageDlg( «DLL жүктеу мүмкін емес», mtError, [ mbOK], 0 );

Шығу ;

Соңы ;

@HelloWorld:= GetProcAddress(DLLInstance, "HelloWorld" );

егер @HelloWorld нөл болса

HelloWorld (өзіндік)

басқа

MessageDlg( «Қажетті процедура табылмады!»., mtError, [ mbOK], 0 );

FreeLibrary(DLLInstance);

Соңы ;

DLL файлдары тек кодты ғана емес, пішіндерді де сақтай алады.
Сонымен қатар, динамикалық кітапханада пішіндерді жасау және орналастыру жұмыс істеуден көп айырмашылығы жоқ
кәдімгі жобадағы пішіндермен. Алдымен кітапхананы қалай жазуға болатынын қарастырамыз,
пішіндерді қамтиды, содан кейін DLL-де MDI технологиясын пайдалану туралы айтатын боламыз.
Мен мысал арқылы пішіні бар DLL әзірлеуін көрсетемін.
Сонымен, алдымен жаңа динамикалық кітапхана жобасын жасайық.
Ол үшін Файл|Жаңа мәзір пунктін таңдап, DLL белгішесін екі рет шертіңіз.
Осыдан кейін сіз келесіге ұқсас кодты көресіз:

Алынған жобаны сақтаңыз. Оны DllForms.dpr деп атаймыз.
Енді сізге жаңа пішін жасау керек. Мұны әртүрлі жолдармен жасауға болады.
Мысалы, Файл|Жаңа пішін мәзір элементін таңдау арқылы. Пішінге кейбір компоненттерді қосыңыз.
Формаға DllForm ат қойып, алынған модульді DllFormUnit.pas атауымен сақтайық.
Жобаның негізгі модуліне оралайық және оған ShowForm функциясын орналастырайық, оның міндетіне мыналар кіреді:
пішінді құру және оны экранда көрсету. Ол үшін төмендегі кодты пайдаланыңыз.

Пішін: TDLLForm;

БАСТА

Нәтиже:= Form.ShowModal ;

Form.Free ;

Соңы ;

Жоба қатесіз құрастырылуы үшін Пішіндер модулін пайдалану бөліміне қосу керек екенін ескеріңіз.
Біз экспорт кілт сөзі арқылы функциямызды экспорттаймыз:
экспорт
ShowForm;
Біз жобаны құрастырамыз және dllforms.dll файлын аламыз. Бұл қарапайым қадамдар бәрі
ShowForm функциясы stdcall кілт сөзі арқылы жарияланғанын ескеру үшін не істеу керек.
Ол компиляторға функцияны экспорттау кезінде конвенцияны пайдалану туралы сигнал береді
стандартты қоңырау шалу шарты бойынша. Функцияны экспорттау осылай жасайды
әзірленген DLL-ны Delphi-де жасалған қолданбалы бағдарламаларда ғана емес қолдану мүмкіндігі.
Шақыру конвенциялары функцияны шақыру кезінде аргументтердің қалай жіберілетінін анықтайды.
Бес негізгі конвенция бар: stdcall, cdecl, pascal, register және safecall.
Бұл туралы қосымша ақпаратты Delphi анықтамалық файлындағы «Қоңырау шалу шарты» бөлімінен білуге ​​болады.
Сондай-ақ, ShowForm функциясы қайтаратын мән екенін ескеріңіз
ShowModal мәніне сәйкес келеді. Осылайша сіз кейбір ақпаратты тасымалдай аласыз
шақырушы өтінішке пішіннің күйі туралы.
Төменде екі тізім бар, олардың біріншісінде файлдың толық коды бар
DLL жобасы (формасы бар модуль мұнда көрсетілмеген), ал екіншісі шақырылатын қолданба модулі,
ол біз әзірлеген кітапхананы пайдаланады.

libraryDllForms;

пайдаланады

"DllFormUnit.pas" (DllForm) ішіндегі DllFormUnit ;

($R *.RES)

ShowForm функциясы: Integer ; stdcall;

Пішін: TDLLForm;

БАСТА

Form:= TDLLForm.Create(Application) ;

Нәтиже:= Form.ShowModal ;

Form.Free ;

Соңы ;

БАСТА

Соңы.


TestAppUnit бірлігі;

интерфейс

пайдаланады

Windows, хабарлар, SysUtils, сыныптар, графика,

Басқару элементтері, пішіндер, диалогтар, StdCtrls;

түрі

TForm1 = сынып (TForm)

1 түймесі: TB түймесі;

процедура Button1Click(Жіберуші: TObject ) ;

жеке

(Жеке декларациялар)

қоғамдық

(Жария декларациялар)

Соңы ;

Пішін1: TForm1;

ShowForm функциясы: Integer ; stdcall;

Сыртқы "dllforms.dll" ;

жүзеге асыру

($R *.DFM)

процедура TForm1.Button1Click (Жіберуші: TObject );

БАСТА

Соңы ;

Соңы.

Функцияны экспорттау кезінде stdcall кілт сөзі де қолданылғанын ескеріңіз.
DLL файлдарындағы еншілес пішіндермен жұмыс істеуге ерекше назар аудару керек. Егер, мысалы,
шақырушы қолданбада негізгі пішінде MDIForm тең FormStyle сипат мәні бар,
содан кейін DLL ішінен MDIChild пішінін шақыруға тырысқанда, экранда қате туралы хабар пайда болады,
ол белсенді MDI пішіні жоқ екенін айтады.
Сіз еншілес терезені көрсетуге тырысқан кезде, VCL дұрыстығын тексереді
Қосымшаның негізгі пішінінің FormStyle сипаттары. Дегенмен, біздің жағдайда бәрі рас сияқты.
Сонымен, мәміле қандай? Мәселе мынада, мұндай тексеруді орындау кезінде Қолданба нысаны қарастырылады,
шақырушы қолданбаға емес, динамикалық кітапхананың өзіне тиесілі.
Әрине, DLL негізгі пішіні болмағандықтан, тексеру қате жібереді.
Бұл жағдайды болдырмау үшін динамикалық кітапхананың Қолданба нысанын тағайындау керек
шақырушы қолданбаның қолданба объектісі. Әрине, бұл жағдайда ғана жұмыс істейді
шақырушы бағдарлама VCL қолданбасы болғанда. Сонымен қатар, кітапхананы жадтан түсіру алдында
кітапхананың Application нысанының мәнін бастапқы күйіне қайтару қажет.
Бұл жад менеджеріне кітапханада орналасқан жедел жадты тазалауға мүмкіндік береді.
Сондықтан кітапхананың жергілікті Application нысанына көрсеткішті сақтау керек
оның мәнін қалпына келтіру үшін пайдалануға болатын жаһандық айнымалыда.
Сонымен, сәл артқа шегініп, біз жұмыс істеуге қажетті қадамдарды орналастырайық
DLL MDIChild пішіндерінде.
Динамикалық кітапханада TApplication типті ғаламдық айнымалыны жасаймыз.
Бағдарлама DLL нысанына көрсеткішті жаһандық айнымалыда сақтаймыз.
Динамикалық кітапхананың Application объектісіне Қолданбаға көрсеткіш тағайындаймыз
қоңырау шалу қолданбасы.
Біз MDIChild пішінін жасаймыз және онымен жұмыс істейміз.
Динамикалық кітапхананың Application нысанының мәнін бастапқы күйіне қайтарамыз
және жадтан DLL файлын босатыңыз.
Бірінші қадам қарапайым. Біз жай ғана келесі кодты DLL модулінің жоғарғы жағына орналастырамыз:
var
DllApp:TApplication;
Содан кейін біз Application объектінің мәнін өзгертетін процедураны жасаймыз және еншілес пішінді жасаймыз.
Процедура келесідей көрінуі мүмкін:

ShowMDIChild процедурасы(MainApp: TApplication) ;

Бала: TMDIChild;

БАСТА

Егер тағайындалмаған болса (DllApp) бастаңыз

DllApp:= Қолданба;

Қолданба:= MainApp;

Соңы ;

Child:= TMDIChild.Create(Application.MainForm) ;

Child.Show ;

Соңы ;

Енді бізге тек Қолданба нысанының қайтару мәнін беру қажет
бастапқы күйіне дейін. Мұны MyDllProc процедурасы арқылы орындаймыз:

процедура MyDLLProc(Себебі: Integer );

БАСТА

Егер Себеп = DLL_PROCESS_DETACH болса

(DLL жүктелмеген. Қолданба көрсеткішінің мәнін қалпына келтіріңіз)

Егер тағайындалған болса (DllApp).

Қолданба:= DllApp;

Соңы ;

Қорытындының орнына.
Динамикалық сілтеме кітапханаларын пайдалану бірінші көзқараста көрінетіндей қиын емес.

Динамикалық сілтеме кітапханаларын пайдалану бірінші көзқараста көрінетіндей қиын емес.
DLL файлдары қолданба жұмысын оңтайландыруға кең мүмкіндіктер береді,
сондай-ақ бағдарламашылардың өздерінің жұмысы. DLL пайдаланыңыз, мүмкін сіздің өміріңіз оңайырақ болады!
http://subscribe.ru/
Электрондық пошта: [электрондық пошта қорғалған]Іздеу
Subscribe.Ru сайтындағы APORT сайтына

Delphi бағдарламалау ортасы DLL файлдарын жылдам құру үшін кіріктірілген құралдармен қамтамасыз етеді.

Нақты болу үшін функцияны қамтитын кітапхананы жасайық

GetArea(a, b, c: REAL):REAL.

Бұл функция кіріс ретінде үшбұрыштың қабырғаларының ұзындықтарын қабылдайды. Функция берілген үшбұрыштың ауданын қайтарады:

p:=(a+b+c)/2;

Нәтиже:=SQRT(p*(p-a)*(p-b)*(p-c))

D іске қосыңызэлфи, содан кейін біз дәстүрлі емес әрекет етеміз. F мәзір элементтерін таңдаңызileНewОсонда, N қойындысында ашылатын терезедеewDLL W белгішесін басыңызизард. (алгоритм нұсқаға байланысты)

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

Енді оператордан кейінПАЙДАЛАНАТЫНбіз функциямыздың мәтінін жазамыз, бірақ тақырыпта кейбір өзгерістер бар:

ФУНКЦИЯ GetArea(a, b, c:REAL):REAL;экспорт;

EXPORT кілт сөзі функцияның экспортталатынын және сыртқы бағдарламалардан көрінетінін көрсетеді.

Функция мәтінінен кейін біз қосамыз

GetArea;

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

Кітапхананы басқару мүмкін емес, оны тек құрастыруға болады. Ол үшін жоба → Құру мәзір тармағын таңдаңыз. Егер бәрі дұрыс орындалса, ағымдағы каталогтағы дискіде geta.dll деп аталатын файл жасалады. Бұл біздің кітапхана.

Маңызды ескерту: Кітапханада орналасқан процедуралар мен функцияларға STRING типті параметрлерді беру кезінде белгілі бір нәзіктік бар.

STRING түрінің параметрлерін өткізу мүмкіндігі болу үшін кітапхананың да, оны шақыратын бағдарламаның да USES мәлімдемелерінде ShareMem модулінің қосылымын көрсету керек, тіпті бұл модуль тізімде бірінші болу үшін. . Сонымен қатар, кітапханамен бірге borlndmm.dll файлын қосу керек (ол Delphi дистрибутивіне кіреді). Бұл жағдайды болдырмау оңай: мәтін түрінің параметрлері үшін ShortString деректер түрлерін (бұл кәдімгі жол, бірақ ұзындығы 255 таңбаға дейін) және PChar (мәтін жолына көрсеткіш) пайдалану керек.

dll файлына қоңырау шалыңыз

DLL файлынан процедуралар мен функцияларды шақырудың екі жолы бар. Бірінші жағдайда, біз бағдарламаны әзірлеу кезеңінде біз оған қандай DLL қосылатынын алдын ала білеміз (көбінесе біз бұл DLL-ді өзіміз жасаймыз). Екінші жағдайда біз ерікті кітапханаға, соның ішінде «шетелдік» кітапханаға қосыламыз.

Статикалық байланыстыру

Бірінші әдісті іске асыру үшін шақырылады статикалық байланыстыру, жаңа тұрақты қолданбаны жасаңыз, пішінге LabeledEdit1...LabeledEdit3 үш енгізу өрісін, түймені және Tlabel компонентін орналастырыңыз. IMPLEMENTATION мәлімдемесінен кейін geta.dll кітапханасынан GetArea функциясын импорттайтын жолды қосыңыз:

GetArea(a,b,c:real):REAL функциясы; FAR; СЫРТҚЫ «гета»;

EXTERNAL сөзі бұл функцияның денесі көрсетілген атаумен кітапханада орналасқанын көрсетеді, ал FAR сөзі шақыратын бағдарлама жадтың бір бетінде орналасқандықтан қажет «ұзын» төрт байт адрестерді пайдалануды көрсетеді. , ал DLL кітапханасы басқасында. Әрине, geta.dll файлы ағымдағы қолданбаның барлық файлдары орналасқан каталогқа орналастырылуы керек.

Түймені басу өңдегішінде массив жасап, оны кітапхана функциясына беру керек және нәтижені экранда көрсету керек:

процедура TForm1.Button1Click(Sender: TObject);

DLL файлдарымен жұмыс істеу

DLL- Dynamic Link Library - бұл әртүрлі бағдарламаларда бірдей функцияларды қайта пайдалануға мүмкіндік беретін динамикалық сілтеме кітапханасы. Шын мәнінде, бұл өте ыңғайлы құрал, әсіресе кітапхана бір рет жазылғаннан кейін көптеген бағдарламаларда қолданылуы мүмкін. Бүгінгі сабақта біз dll файлдарымен жұмыс істеуді және әрине оларды құруды үйренеміз!

Ал, бастайық!

Алдымен, бірінші динамикалық сілтеме кітапханасын жасайық! Біз Delphi-ге өтіп, бірден File -> New -> Other мәзіріне өтеміз.

Тізімнен Dynamic-Link Library таңдаңыз (Delphi 2009 нұсқасынан бұрынғы нұсқаларда элемент DLL шебері деп аталады).

Нәтижесінде бізде тек код бар терезе бар; бұл жерде ешқандай пішін жоқ!

Енді қызық басталады. Кітапханадағы алғашқы процедураларымызды жазайық.

libraryProject2; //Dll жасағанда //бағдарламаның орнына кітапхана сөзі қолданылғанын байқаған боларсыз. //Мағынасы кітапхана. SysUtils, диалогтық терезелер, Класстарды пайдаланады; // Назар аударыңыз! Бұл модульдерді көрсетуді ұмытпаңыз, әйтпесе код жұмыс істемейді ($R *.res) (БҰЛ БӨЛІМ DLL КОДЫ) Процедура FirstCall; stdcall; экспорт; //Stdcall – Бұл оператордың көмегімен параметрлер стекке //оңнан солға қарай орналастырылады және стандартты мәнге теңестіріледі //Экспорт, негізінен, процедураның //экспортын нақтылау үшін пайдаланылады; немесе функция. ShowMessage бастау («Dll-дегі бірінші процедурам»); //Экрандағы хабарламаны шақыру End; DoubleCall процедурасы; stdcall; экспорт; ShowMessage бастау («Менің екінші процедурам»); //Экрандағы хабарламаны шақыру End; FirstCall, DoubleCall экспорттайды; //Экспортта экспортталған элементтердің тізімі бар. //Ол кейінірек кейбір бағдарлама арқылы импортталады. бастау Аяқтау.

Әзірге осында тоқтаймыз, өйткені... қарапайым мысал үшін бұл жеткілікті болады. Енді біз жобамызды сақтаймыз, мен оны Project2.dll деген атпен сақтадым және кітапхананы құрастыру үшін CTRL+F9 пернелер тіркесімін басыңыз. dpr файлын сақтаған қалтада dll кеңейтімі бар файл пайда болады, бұл біздің жаңа ғана жасалған кітапханамыз. Менде Project2.dll деп аталады

Енді осы кітапханадан процедураларды шақыруды бастайық. Біз стандартты схемаға сәйкес жаңа қосымшаны жасаймыз. Біздің алдымызда ерекше ештеңе жоқ, тек пішін. Жаңа қолданбаны кейбір қалтаға сақтаңыз. Жаңадан жасалған dll кітапханасын сол қалтаға көшіріңіз. Анау. бұл мысалда Project2.dll

Енді кітапханадан функцияларды шақыру жолын таңдау керек. Барлығы екі қоңырау әдісі бар.

№1 әдіс

Мүмкін бұл кітапханада орналасқан процедураларды шақырудың ең қарапайым әдісі.

Бір ғана кітапханамен жұмыс істеуге өте ыңғайлы.

Мінеки біз...

Іске асыру кілт сөзінен кейін келесі кодты жазыңыз:

Мұнда, сіз ойлағандай, біз бағдарламаға процедураларымыздың атауларын айтамыз және олар DLL кітапханасында орналасқан деп айтамыз, менің жағдайда Project2.dll деп аталады.

Енді осы процедураларды шақыру үшін кодтың кез келген жеріне олардың атауларын енгізу керек, оны қазір жасаймыз. Стандартты қойындысынан пішінге 2 түйме құрамдастарын тастаңыз және әрқайсысында OnClick оқиға өңдегішін жасаңыз

Бірінші түймені басу:

Екінші түймені басыңыз:

Осымен болды!

№2 әдіс:

Біріншісіне қарағанда күрделірек, бірақ оның артықшылықтары бар, ең бастысы, ол плагиндер үшін өте қолайлы.

Бұл әдісті қолдану үшін ең алдымен бірнеше ғаламдық айнымалыларды жариялаймыз:

Содан кейін іске асыру кілт сөзінен кейін кітапханамызды жүктейтін процедураны жазамыз:

LoadMyLibrary процедурасы(ФайлАты: Жол);БАСТА LibHandle:= LoadLibrary(PWideChar(FileName));//Кітапхана жүктелуде! // Назар аударыңыз! 2009 Delphi нұсқасынан төмен нұсқалар үшін PChar Егер LibHandle = 0 болса, MessageBox(0,"Кітапхананы жүктеу мүмкін емес",0,0); Шығу; Соңы; FirstCall:= GetProcAddress(LibHandle, "Алғашқы қоңырау");//Нысанға көрсеткіш алу //Кітапхана модуліне 1-ші параметр сілтемесі //dll файлындағы нысанның 2-ші параметр атауы DoubleCall:= GetProcAddress(LibHandle,"DoubleCall"); @FirstCall = нөл болса, бастаңыз//Кітапханада осы функцияның бар-жоғын тексеріңіз. MessageBox(0,"Кітапхананы жүктеу мүмкін емес",0,0); Шығу; Соңы; @DoubleCall = нөл болса, бастаңыз//Кітапханада осы функцияның бар-жоғын тексеріңіз. MessageBox(0,"Кітапхананы жүктеу мүмкін емес",0,0); Шығу; Соңы; Соңы

Содан кейін пішінде біз OnCreate оқиға өңдеушісін жасаймыз, онда жаңадан жасалған процедураны пайдаланып кітапханамызды жүктейміз.

TForm1.FormCreate процедурасы(Sender: TObject);БАСТА LoadMyLibrary («Project2.dll»);Соңы;

Енді тағы да кітапханамыздан қажетті процедураларды шақыру үшін кодтың кез келген жеріне олардың атын енгізу жеткілікті. Бұл әрекетті орындау үшін, Стандартты қойындысынан пішінге 2 түйме құрамдастарын тастаңыз және әрқайсысында OnClick оқиға өңдегішін жасаңыз.

Бірінші түймені басу:

TForm1.Button1Click процедурасы(Жіберуші: TObject);Бірінші қоңырауды бастау; // dll End ішінде орналасқан процедураның аты;

Екінші түймені басыңыз:

TForm1.Button2Click процедурасы(Sender: TObject); DoubleCall бастау; // dll End ішінде орналасқан процедураның аты;

Соңында біз пішінде OnDestroy оқиға өңдеушісін жасаймыз, онда DLL кітапханасын жадтан босатамыз.

Осымен болды! Екінші әдіс өте қиын болып шықты, бірақ оның артықшылығы кітапханада сақталған нысанды нақтылау болып табылады.