DLL
Вызов DLL из внешней программы
Библиотеку DLL можно связать с приложением двумя способами:
- статическим связыванием
- динамическим связыванием
Статическое связывание самое простое, оно подразумевает, что DLL будет загружена сразу, как только приложение начнет выполняться. Это самый простой способ использования DLL, обращение к процедурам и функциям динамической библиотеки такое же, как к обычным процедурам и функциям. Но есть и минусы использования статистического связывания.
Во-первых, при загрузке программы должны подгружаться и все используемые DLL, а это увеличивает время загрузки (при современной технике, правда, ненамного).
Во-вторых, чтобы пользователь мог работать с программой, он должен иметь все эти используемые DLL. Обычно конечно, так и есть, но бывают и исключения. Можно было бы раздать незарегистрированным пользователям усеченную версию программы, без некоторых ключевых DLL. Тогда они могли бы пользоваться программой, но не всеми её возможностями, а только основными. Зарегистрированным пользователям можно было бы дополнительно рассылать остальные DLL. При статическом связывании это недоступно.
В-третьих, при статическом связывании все загруженные DLL занимают память всё время, что работает программа, вне зависимости от того, использует ли она эти DLL в настоящее время, или нет.
Динамическое связывание подразумевает, что требуемая DLL будет подгружаться только тогда, когда требуется выполнить какую-то процедуру или функцию из неё. После чего DLL можно выгрузить, освободив память. Динамическое связывание также имеет плюсы и минусы. Плюсы в том, что программу можно использовать, не имея всех DLL. Загрузка программы будет осуществляться быстрее, поскольку DLL будут подгружаться по мере необходимости, а не вместе с программой.
Минусы же в том, что из-за необходимости подгружать и выгружать библиотеку, будет увеличиваться время обращения к её функциям и процедурам. Кроме того, само обращение к ним будет намного сложнее.
Статическое связывание DLL
Разберем вначале более простой способ. Откройте Lazarus с новым проектом, имя формы измените на fMain, в Caption напишите "Статическое связывание DLL", установите свойства BorderStyle в bsDialog, а Position в poDesktopCenter. Нажмите кнопку "Сохранить всё" и сохраните проект под именем Proba в папку 26-02. Модуль формы назовите как обычно, Main.
Теперь скопируйте файл MyFirstDLL.dll из папки 26-01 в папку 26-02, чтобы наш проект мог пользоваться этой DLL.
Далее, перейдите в Редактор кода. Чтобы мы могли использовать функции и процедуры DLL, их нужно объявить так же, как в DLL. Объявления нужно делать сразу после ключевого слова implementation, и после директивы процессору {$R *.lfm}:
implementation {$R *.lfm} function Code(s: PChar; Key: integer): PChar; stdcall; external 'MyFirstDLL.dll'; function BeforeBirthday(Birthday:TDateTime): Integer; stdcall; external 'MyFirstDLL.dll'; function ArToRom(N: Integer): PChar; stdcall; external 'MyFirstDLL.dll'; function RomToAr(s: PChar): Integer; stdcall; external 'MyFirstDLL.dll';
Как видите, объявление требуемых нам функций такое же, каким было в DLL, но также после объявления была добавлена директива external:
external 'MyFirstDLL.dll';
которая означает, что эти функции программа должна искать в соответствующем файле динамической библиотеки, ведь программа может использовать несколько DLL. И это всё, что нужно для статического связывания. В дальнейшем мы сможем обращаться к этим функциям, как к любым другим.
Займемся компонентами. Установите на форму метку TLabel, в Caption которой напишите "Укажите день рождения:". Далее установите компонент TDateEdit с вкладки Misc Палитры компонентов, здесь пользователь будет вводить или выбирать требуемую для проверки дату рождения. Свойство Name компонента переименуйте в DE1. Правее установите простую кнопку TButton, в Caption которой напишите "До дня рождения", а Name переименуйте в bBeforeBirthday.
Ниже установим компоненты для проверки перевода формата цифр из арабских в римские, и наоборот. Вначале установим поясняющую метку TLabel, в Caption которой напишем "Укажите целое число от 1 до 2147483647:". Далее установим строку TEdit, которую переименуем в eNumbers, и очистим свойство Text. Ниже установим две простые кнопки TButton, которые переименуем в bArToRom и bRomToAr, а в Caption этих кнопок напишем соответственно, "Арабское в римское" и "Римское в арабское".
Наконец, займемся компонентами для шифрования текста. Сначала метку TLabel с текстом в Caption "Впишите текст:". Далее строку TEdit, которую переименуем в eCode, и у которой очистим свойство Text. Ниже установим простую кнопку TButton, переименуем её в bCode, и в свойстве Caption напишем "Шифровать/дешифровать". Измените положение и размеры компонентов так, чтобы ваша форма выглядела примерно так:
Нам осталось написать код события OnClick для наших четырех кнопок, и опробовать в действии работу с DLL. Код OnClick для кнопки bBeforeBirthday будет такой:
procedure TfMain.bBeforeBirthdayClick(Sender: TObject); begin if DE1.Text = '' then exit; ShowMessage('До дня рождения осталось ' + IntToStr(BeforeBirthday(DE1.Date)) + ' дней'); end;
Просто, не правда ли? Если пользователь не выбрал дня рождения, оставив строку DE1 пустой, мы выходим из процедуры, ничего не делая. Иначе мы выводим сообщение со сборной из трех частей строкой. Вызов функции из DLL:
IntToStr(BeforeBirthday(DE1.Date))
вернет нам в виде строки количество оставшихся до дня рождения дней.
Для кнопки bArToRom код события OnClick будет еще проще:
procedure TfMain.bArToRomClick(Sender: TObject); begin if eNumbers.Text = '' then exit; eNumbers.Text:= ArToRom(StrToInt(eNumbers.Text)); end;
Здесь мы делаем единственную проверку - не пуста ли строка eNumbers. Имейте в виду, что в реальном приложении вам еще потребовалась бы проверка на содержимое текста: число ли это, целое ли, входит ли оно в диапазон от 1 до 2 147 483 647? В нашей пробной программе для экономии места мы предполагаем, что пользователь не будет вводить некорректных данных.
Для кнопки bRomToAr код похожий:
procedure TfMain.bRomToArClick(Sender: TObject); begin if eNumbers.Text = '' then exit; eNumbers.Text:= IntToStr(RomToAr(PChar(eNumbers.Text))); end;
В реальной программе вам также пришлось бы делать проверку на корректность ввода данных римских цифр. Здесь же мы будем считать, что пользователь ввел правильные римские цифры.
Ну и, наконец, для кнопки bCode код будет таким:
procedure TfMain.bCodeClick(Sender: TObject); begin if eCode.Text = '' then exit; eCode.Text:= Code(PChar(eCode.Text), 10); end;
Выше я советовал вам выбирать размер ключа в диапазоне от 1 до 30, в вызове функции Code из DLL я указал размер ключа 10. Вот, собственно, и все. Сохраните проект и запустите его. Если вы все сделали правильно, ваша программа будет работать, как надо: