Difference between revisions of "DLL dynamically load/ru"
From Lazarus wiki
Jump to navigationJump to search (Created page with "{{DLL_dynamically_load}} The tutorial shows how a DLL (Dynamic Link Library) is loaded dynamically . The DLL (DLLTest.dll) referred to in the example below: <syntaxhighligh...") |
|||
Line 1: | Line 1: | ||
{{DLL_dynamically_load}} | {{DLL_dynamically_load}} | ||
− | + | В руководстве показано, как динамически загружается DLL (библиотека динамической компоновки). | |
− | + | Библиотека DLL (DLLTest.dll), указанная в примере ниже: | |
<syntaxhighlight lang=pascal> | <syntaxhighlight lang=pascal> | ||
Line 15: | Line 15: | ||
{$R *.res} | {$R *.res} | ||
− | // | + | // Подпрограмма DLL |
function funStringBack(strIn : string) : PChar; | function funStringBack(strIn : string) : PChar; | ||
begin | begin | ||
Line 22: | Line 22: | ||
− | // | + | // Экспортированная подпрограмма(ы) |
exports | exports | ||
funStringBack; | funStringBack; | ||
Line 30: | Line 30: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Что я должен делать: | |
+ | * Определить память | ||
+ | ** Необходимо создать тип данных, который точно соответствует (внешней) подпрограмме, которая должна быть импортирована из DLL. | ||
+ | * Зарезервировать память | ||
+ | ** Память должна быть зарезервирована для переменной (поля данных), которой назначен указанный выше тип данных. | ||
+ | ** Память должна быть зарезервирована для дескриптора, которому дескриптор DLL будет назначен позже. | ||
+ | * Назначить DLL и внешнюю подпрограмму и принимаемые данные | ||
+ | ** Вызвать DLL и назначить дескриптору DLL дескриптор. | ||
+ | ** Указатель переменных должен быть заменен на память внешней подпрограммы. | ||
+ | ** Результат внешней подпрограммы должен быть принят. | ||
+ | * Освободить всю память | ||
+ | ** Указатель на переменные должен снова указывать на недопустимую область памяти (:= nil), чтобы освободить внешнюю подпрограмму. | ||
+ | ** Память DLL необходимо снова освободить. | ||
− | + | Интегрируйте, используйте и выпустите подпрограмму DLL в вашей собственной программе: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang=pascal> | <syntaxhighlight lang=pascal> | ||
Line 55: | Line 54: | ||
Include function funDll : string; | Include function funDll : string; | ||
type | type | ||
− | // | + | // Определение вызываемой подпрограммы, как задано в DLL, которая будет использоваться |
TfunStringBack = function(strIn : string) : PChar; stdcall; | TfunStringBack = function(strIn : string) : PChar; stdcall; | ||
var | var | ||
− | // | + | // Создаем подходящую переменную (поле данных) для подпрограммы DLL |
funStringBack : TfunStringBack; | funStringBack : TfunStringBack; | ||
− | // | + | // Создаем дескриптор для DLL |
LibHandle : THandle; | LibHandle : THandle; | ||
begin | begin | ||
− | // | + | // Получаем дескриптор библиотеки, которая будет использоваться |
LibHandle := LoadLibrary(PChar('DLLTest.dll')); | LibHandle := LoadLibrary(PChar('DLLTest.dll')); | ||
− | // | + | // Проверяем успешность загрузки DLL |
if LibHandle <> 0 then | if LibHandle <> 0 then | ||
begin | begin | ||
− | // | + | // Назначаем адрес вызова подпрограммы переменной funStringBack |
− | // 'funStringBack' | + | // 'funStringBack' из DLL DLLTest.dll |
Pointer(funStringBack) := GetProcAddress(LibHandle, 'funStringBack'); | Pointer(funStringBack) := GetProcAddress(LibHandle, 'funStringBack'); | ||
− | // | + | // Проверяет, был ли возвращен действительный адрес |
if @funStringBack <> nil then | if @funStringBack <> nil then | ||
Result := funStringBack('hello world'); | Result := funStringBack('hello world'); | ||
end; | end; | ||
− | // | + | // освобождаем память |
funStringBack := nil; | funStringBack := nil; | ||
FreeLibrary(LibHandle); | FreeLibrary(LibHandle); |
Latest revision as of 18:31, 15 December 2020
Эта статья относится только к Windows.
См. также: Multiplatform Programming Guide
│
Deutsch (de) │
English (en) │
русский (ru) │
中文(中国大陆) (zh_CN) │
В руководстве показано, как динамически загружается DLL (библиотека динамической компоновки).
Библиотека DLL (DLLTest.dll), указанная в примере ниже:
library info;
{$mode objfpc} {$H+}
uses
SysUtils;
{$R *.res}
// Подпрограмма DLL
function funStringBack(strIn : string) : PChar;
begin
funStringBack := PChar(UpperCase(strIn));
end ;
// Экспортированная подпрограмма(ы)
exports
funStringBack;
begin
end.
Что я должен делать:
- Определить память
- Необходимо создать тип данных, который точно соответствует (внешней) подпрограмме, которая должна быть импортирована из DLL.
- Зарезервировать память
- Память должна быть зарезервирована для переменной (поля данных), которой назначен указанный выше тип данных.
- Память должна быть зарезервирована для дескриптора, которому дескриптор DLL будет назначен позже.
- Назначить DLL и внешнюю подпрограмму и принимаемые данные
- Вызвать DLL и назначить дескриптору DLL дескриптор.
- Указатель переменных должен быть заменен на память внешней подпрограммы.
- Результат внешней подпрограммы должен быть принят.
- Освободить всю память
- Указатель на переменные должен снова указывать на недопустимую область памяти (:= nil), чтобы освободить внешнюю подпрограмму.
- Память DLL необходимо снова освободить.
Интегрируйте, используйте и выпустите подпрограмму DLL в вашей собственной программе:
uses
Windows, ...;
...
Include function funDll : string;
type
// Определение вызываемой подпрограммы, как задано в DLL, которая будет использоваться
TfunStringBack = function(strIn : string) : PChar; stdcall;
var
// Создаем подходящую переменную (поле данных) для подпрограммы DLL
funStringBack : TfunStringBack;
// Создаем дескриптор для DLL
LibHandle : THandle;
begin
// Получаем дескриптор библиотеки, которая будет использоваться
LibHandle := LoadLibrary(PChar('DLLTest.dll'));
// Проверяем успешность загрузки DLL
if LibHandle <> 0 then
begin
// Назначаем адрес вызова подпрограммы переменной funStringBack
// 'funStringBack' из DLL DLLTest.dll
Pointer(funStringBack) := GetProcAddress(LibHandle, 'funStringBack');
// Проверяет, был ли возвращен действительный адрес
if @funStringBack <> nil then
Result := funStringBack('hello world');
end;
// освобождаем память
funStringBack := nil;
FreeLibrary(LibHandle);
end;
...