Библиотека программиста

«Ни один ремесленник, который стремится к вершинам своей профессии, не примет негодных инструментов; и ни один производитель, который ценит качество работы, не будет упрашивать ремесленника принять их»

Главная страница > Язык Object Pascal > 36. Разработка собственных библиотек

36. Разработка собственных библиотек

Структура файла библиотеки идентична структуре файла проекта, только вместо слова program используется library. Создание библиотеки (в Delphi 5) удобно выполнить с помощью темы меню File/New/New/DLL. Пример собственной библиотеки (см. проект MyDll.dpr):

Library MyDll;

uses …;

Function Min ( X, Y: Integer) : Integer;

Begin

if X < Y then Min := X else Min := Y;

End;

Function Max(X, Y: Integer) : Integer;

Begin

if X > Y then Max := X else Max := Y;

End;

exports

Min index 1,

Max index 2;

BEGIN

{секция инициализации}

END.

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

Библиотека может состоять из нескольких модулей. В этом случае библиотечный файл (начинающийся со слова library) часто включает только предложения uses, exports и код инициализации. Например:

library Editors;

uses EdInit, EdInOut, EdFormat, EdPrint;

exports

InitEditors index 1,

SetErrorHandler index 53;

begin

InitLibrary;

end.

Библиотека экспортирует только те подпрограммы, которые объявлены в объявлении exports.

Предложение exports. Подпрограмма экспортируется библиотекой (или программой), если она указана в предложении exports. Это предложение имеет такой формат:

exports

routine_1, routine_2, …, routine_n;

Каждая экспортируемая подпрограмма описывается по формату:

имя_подпрограммы (список_параметров) index номер name 'внешнее_имя'

Здесь все элементы описания, за исключением имя_подпрограммы, являются необязательными. Имя_подпрограммы – это идентификатор описанной выше (или в другом модуле) процедуры или функции, причем он может быть уточнен именем модуля. Список­_параметров указывается в случае экспорта перегруженных функций, например:

exports

Divide(X, Y: Integer) name 'Divide_Ints',

Divide(X, Y: Real) name 'Divide_Reals';

Элемент описания index, сопровождаемый целочисленной константой 1..2147483647, используется только для обратной совместимости. Если он не указан, подпрограмме назначается индекс в соответствии с местоположением ее описания в предложении exports.

Слово name, сопровождаемое строковой константой, используется для экспорта подпрограммы под другим (не оригинальным) именем. Если имя опущено, то подпрограмма экспортируется под своим оригинальным именем (с учетом орфографии и регистра).

Предложение exports может встречаться в любом месте программы, где допустимо делать описания, и любое число раз. Главная программа редко содержит это предложение, так как Windows не разрешает приложениям экспортировать подпрограммы.

Код инициализации библиотеки. Операторы, указанные в секции инициализации библиотеки, выполняются один раз при ее загрузке. Обычно в этой секции выполняется инициализация переменных и регистрация оконных классов. Также в этой секции может быть установлена процедура выхода с использованием переменной ExitProc. Эта процедура выполняется при выгрузке библиотеки.

Также в секции инициализации можно присвоить переменной ExitCode ненулевое значение в том случае, если корректная работа подпрограмм библиотеки по какой-либо причине невозможна. В такой ситуации библиотека автоматически выгружается и приложение, вызвавшее ее загрузку, уведомляется об этом. Аналогичным образом, если в процессе выполнения секции инициализации возникает исключительная ситуация, библиотека не загружается и сответствующее приложение получает уведомление об этом. Пример библиотеки с секцией инициализации:

Library Test;

var

SaveExit : pointer;

Procedure LibExit;

Begin

// операторы функции

ExitProc := SaveExit; { восстановление цепочки для вызова стандартной

процедуры выхода}

End;

BEGIN

// код инициализации библиотеки

SaveExit := ExitProc; // запоминаем адрес стандартной процедуры

ExitProc := @LibExit; // устанавливаем свою процедуру выхода

END.

Когда библиотека выгружается, ее процедура выхода вызывается до тех пор, пока адрес, хранящийся в указателе ExitProc, не станет равным nil. Секции инициализации модулей, подключенных к библиотеке, выполняются до секции инициализации библиотеки, а секции finalization – выполняются после выполнения процедуры выхода из библиотеки.

Исключительные ситуации и DLL.

Когда в библиотеке возникает ИС, но не обрабатывается в ней, она передается вызывающему процессу. Если этот процесс написан на Object Pascal, ИС может быть обработана с помощью операторов try...except.

Менеджер разделяемой памяти(shared-memory manager).

Если библиотека экспортирует подпрограммы, параметрами которых или возвращаемыми результатами являются длинные строки, то библиотека и использующее ее приложение должны использовать модуль ShareMem. Сказанное относится и к тому случаю, когда приложение или библиотека распределяют память с помощью процедур New или GetMem, а освобождение памяти (с помощью Dispose или FreeMem) выполняется в другом модуле.

Модуль ShareMem всегда должен быть первым в списке подключаемых модулей во всех модулях библиотеки и приложения. Модуль ShareMem является интерфейсом для библиотеки BorlandMM.dll, которая предоставляет модулям возможность совместно использовать динамически распределяемую память. Вследствие этого библиотека BorlandMM.dll должна распространяться вместе со всеми такими приложениями.





<< Предыдущая статья
«35. Динамически подключаемые библиотеки»
Следующая статья >>
37. Платформы семейства Windows