{Project file name: c:\example\exdouble\exdouble.dpr}library ExDouble;
// my simple dllfunction calc_double(r: real): real; stdcall;
begin
result := r * 2;
end;
exports
calc_double index 1;
end;
Теперь посмотрим, как её можно загружать:
Статическая загрузка DLL
При таком способе загрузки достаточно поместить файл DLL в директорию приложения или в директорию Windows, или в Windows\System, Windows\Command. Однако, если система не найдёт этого файла в этих директория, то высветится сообщение об ошибке (DLL не найдена, или что-то в этом духе).
unit untMain;
interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private{ Private declarations }public{ Public declarations }end;
var
Form1: TForm1;
implementationfunction calc_double(r: real): real; stdcall; external 'ExDouble.dll';
{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);
begin// в окошке сообщения будет цифра 21
ShowMessage(FloatToStr(calc_double(10.5)));
end;
end.
Динамическая загрузка DLL
При динамической загрузке требуется написать немного больше кода.
А вот как это выглядит:
unit untMain;
interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
Tcalc_double = function ( r: real ): real;
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);
var
hndDLLHandle: THandle;
calc_double: Tcalc_double;
begintry// загружаем dll динамически
hndDLLHandle := loadLibrary ( 'ExDouble.dll' );
if hndDLLHandle <> 0 thenbegin// получаем адрес функции
@calc_double := getProcAddress ( hndDLLHandle, 'calc_double' );
// если адрес функции найденif addr ( calc_double ) <> nilthenbegin// показываем результат ( 21...)
showMessage ( floatToStr ( calc_double ( 10.5 ) ) );
endelse// DLL не найдена ("handleable")
showMessage ( 'Function not exists...' );
endelse// DLL не найдена ("handleable")
showMessage ( 'DLL not found...' );
finally// liberar
freeLibrary ( hndDLLHandle );
end;
end;
end.
Here's a translation of the content into Russian:
Статическое загрузка DLL
В первом примере показано, как статически загружать DLL, что означает, что DLL связывается с исполняемым файлом на этапе компиляции. Этот подход имеет некоторые ограничения, такие как требование наличия DLL в том же каталоге, что и исполняемый файл, или в системном каталоге.
Динамическая загрузка DLL
Второй пример демонстрирует динамическую загрузку DLL, которая позволяет программе загружать DLL в runtime. Этот подход обеспечивает больше гибкости и часто используется при работе с третьими библиотеками.
Предложения по улучшению кода
Вот несколько предложений по улучшению кода:
В примере динамической загрузки DLL рекомендуется проверять, является ли указатель на функцию calc_double валидным перед вызовом этой функции. Это можно сделать, проверив, не равно ли адрес функции нулю.
Рассмотрите использование механизмов обработки ошибок, таких как исключения или коды ошибок, вместо отображения сообщений с текстами ошибок.
В примере динамической загрузки DLL вы не освобождаете handle DLL при освобождении библиотеки. Это может привести к утечкам памяти. Вы должны освободить handle перед освобождением библиотеки.
Вот обновленная версия кода динамической загрузки DLL:
procedureTForm1.Button1Click(Sender:TObject);varhndDLLHandle:THandle;calc_double:Tcalc_double;begintry// Загружаем DLL динамическиhndDLLHandle:=LoadLibrary('ExDouble.dll');ifhndDLLHandle<>0thenbegin// Получаем адрес функции@calc_double:=GetProcAddress(hndDLLHandle,'calc_double');ifAssigned(calc_double)thenbegin// Вызываем функцию и отображаем результатShowMessage(FloatToStr(calc_double(10.5)));endelseShowMessage('Функция не найдена...');endelseShowMessage('DLL не найдена...');finally// Освобождаем handle DLL и библиотекуifhndDLLHandle<>0thenbeginFreeLibrary(hndDLLHandle);end;end;end;
Обратите внимание, что я использовал функцию Assigned для проверки валидности указателя на функцию calc_double, и я освободил handle DLL перед освобождением библиотеки.
Динамическая и статическая загрузка DLL: два способа загрузки библиотеки DLL в приложение, отличающихся способом ее включения в программу.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.