Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Динамическая и статическая загрузка DLL

Delphi , Файловая система , DLL и PlugIns

Динамическая и статическая загрузка DLL

DLL возможно загружать двумя способами:

  1. статически
  2. динамически

Давайте создадим простую библиотеку DLL:


{Project file name: c:\example\exdouble\exdouble.dpr}

library ExDouble;
// my simple dll

function 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;

interface

uses
  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;

implementation

function 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;

interface

uses
  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;
begin
  try
    // загружаем dll динамически
    hndDLLHandle := loadLibrary ( 'ExDouble.dll' );

    if hndDLLHandle <> 0 then
    begin

      // получаем адрес функции
      @calc_double := getProcAddress ( hndDLLHandle, 'calc_double' );

      // если адрес функции найден
      if addr ( calc_double ) <> nil then
      begin
        // показываем результат ( 21...)
        showMessage ( floatToStr ( calc_double ( 10.5 ) ) );
      end
      else
        // DLL не найдена ("handleable")
        showMessage ( 'Function not exists...' );

    end
    else
      // 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. Этот подход обеспечивает больше гибкости и часто используется при работе с третьими библиотеками.

Предложения по улучшению кода

Вот несколько предложений по улучшению кода:

  1. В примере динамической загрузки DLL рекомендуется проверять, является ли указатель на функцию calc_double валидным перед вызовом этой функции. Это можно сделать, проверив, не равно ли адрес функции нулю.
  2. Рассмотрите использование механизмов обработки ошибок, таких как исключения или коды ошибок, вместо отображения сообщений с текстами ошибок.
  3. В примере динамической загрузки DLL вы не освобождаете handle DLL при освобождении библиотеки. Это может привести к утечкам памяти. Вы должны освободить handle перед освобождением библиотеки.

Вот обновленная версия кода динамической загрузки DLL:

procedure TForm1.Button1Click(Sender: TObject);
var
  hndDLLHandle: THandle;
  calc_double: Tcalc_double;
begin
  try
     // Загружаем DLL динамически
    hndDLLHandle := LoadLibrary('ExDouble.dll');

    if hndDLLHandle <> 0 then
    begin
       // Получаем адрес функции
      @calc_double := GetProcAddress(hndDLLHandle, 'calc_double');

      if Assigned(calc_double) then
      begin
         // Вызываем функцию и отображаем результат
        ShowMessage(FloatToStr(calc_double(10.5)));
      end
      else
        ShowMessage('Функция не найдена...');
    end
    else
      ShowMessage('DLL не найдена...');

  finally
     // Освобождаем handle DLL и библиотеку
    if hndDLLHandle <> 0 then
    begin
      FreeLibrary(hndDLLHandle);
    end;
  end;
end;

Обратите внимание, что я использовал функцию Assigned для проверки валидности указателя на функцию calc_double, и я освободил handle DLL перед освобождением библиотеки.

Динамическая и статическая загрузка DLL: два способа загрузки библиотеки DLL в приложение, отличающихся способом ее включения в программу.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: DLL и PlugIns ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 12:20:35/0.0058338642120361/1