Delphi использование библиотек DLL

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

Разработка формы также не вызовет особых трудностей.

При увеличении сложности программы и выполняемого ею функционала, объем кода возрастает и становится практически невозможно оперативно вносить изменения в текст программы и осуществлять её отладку.

На помощь приходят дополнительные модули и формы.

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

В этом случае применяются динамические модули, или так называемые динамические библиотеки, известные под аббревиатуройDLL.

Познакомимся с этими модулями и принципами их использования.

Принципы использования DLL

Динамическая библиотека, при своей разработке, представляет из себя, по сути, точно такой же проект, как и обычный проект при создании программы на Delphi.

В простейшем случае в библиотека состоит из одного модуля. В более сложном — из нескольких модулей.

Примечание. Файл библиотеки обязательно должен располагаться в той же директории, что и EXE файл программы!

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

Переменные, используемые в модуле DLL, видны только внутри DLL и не могут быть экспортированы во внешнюю программу.

Создание DLL

Процесс создания модуля DLL аналогичен процессу создания обычного модуля.

Delphi использование библиотек DLL

Используем File/New/Other…

Открывается диалог:

Delphi использование библиотек DLL

На вкладке NEW выбираем DLL Wizard. Нажав OK, получаем заготовку модуля.

Секции модуля DLL

library Project1;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library’s USES clause AND your project’s (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL—even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. }

uses
Classes;
{$R *.res}
begin
end.


Модуль состоит из двух секций.

Первая секция — предложение uses. Сами функции и процедуры располагаются непосредственно перед оператором begin.

Вторая секция — секция инициализации, начинающаяся оператором begin. Здесь располагаются операторы, которые будут выполнены в процессе загрузки динамической библиотеки. Эта секция используется по мере надобности.

В комментарии говорится, что если из основной программы передаётся длинная строка (тип string), или переменная структурированного типа, содержащая длинные строки (например, запись), или объект, имеющий поля типа string, то необходимо использовать модуль ShareMem.

Из этого модуля осуществляется обращение к менеджеру управления памятью (библиотека BORLNDMM.DLL) и пространство адресов для программы и DLL становится общим.

При использовании модуля ShareMem он должен обязательно присутствовать как в файле проекта программы, так и во всех модулях программы, пользующихся функциями из DLL.

Одновременно он должен присутствовать во всех модулях самой библиотеки DLL, имеющих дело с длинными строками.

Причём он должен стоять первым в списке модулей в предложениях Uses!

В чём тут дело?

А дело в том, что Delphi выделяет память только под основной процесс. В рамках этого процесса выделяется память под потоки (код программы), данные (глобальные данные), стек (локальные данные), кучу.

DLL не имеет своего стека и значения переменных, а также результат работы функции, помещаются в стек вызывающей программы.

Но переменные, хранящиеся с помощью указателя, не могут быть переданы из DLL в программу, так как у DLL нет сведений, какой адрес кучи свободен.

Как решается возникающая проблема, будет рассмотрено в следующих постах.

***

Обновлено: 18.03.2021 — 20:15

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *