If not Assigned (DrawBMP) then




Лабораторная работа №15

Библиотеки

Цель работы: изучить правила оформления и использования динамических библиотек; научится осуществлять статическое и динамическое связывание библиотек.

Любое полноценное приложение операционной системы (32-разрядное приложение, имеющее собственное окно) использует DLL (библиотеки динамической компоновки). Эти библиотеки представляют собой файлы с откомпилированным исполняемым кодом, который используется приложениями и другими DLL. По мере необходимости приложение обращается к библиотекам, вызывая из них нужные функции. Например, выполнимый модуль приложения не содержит кода по отображению окна, вывода в окно и реакции на большинство событий. Перечисленные действия реализуются в системных DLL. В частности, использованием такой технологии удается экономить драгоценные ресурсы, один и тот же код не дублируется многократно, а размещается в памяти единожды.

По существу, динамические библиотеки отличаются от исполняемых файлов тем, что они не могут быть запущены самостоятельно. Для того чтобы динамическая библиотека начала работать, необходимо, чтобы ее вызвала уже запущенная программа или работающая DLL. К одной библиотеке, как правило, может обращаться одновременно несколько приложений. Библиотеку в такой схеме называют сервером, а обслуживаемое им приложение – клиентом. Серверам и клиентам в общем случае могут являться и библиотека, и приложение. В частности, это означает, что некоторая библиотека, в свою очередь, может ”подгружать” функции из другой библиотеки.

Применение динамических библиотек позволяет добиться ряда преимуществ:

< Уменьшается размер исполняемого файла приложения и занимаемые им ресурсы

< Функции DLL могут использовать несколько процессов одновременно

< Управление DLL возлагается на операционную систему

< Внесение изменений в DLL не требует перекомпиляции всего объекта

< Одну DLL могут использовать программы, написанные на разных языках

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

Создание библиотеки

Создадим библиотеку, содержащую полезную функцию, выводящую на окне вызывающего клиента растровое изображение. Для этого в среде Delphi в главном меню выберите пункт File | New и в появившемся окне New Items щёлкните на значке с надписью ‘DLL’.

Чтобы выводимый растр не оказался легко доступным для посторонних глаз, скроем его, поместив в библиотеку. Для этого откройте редактор ресурсов Image Editor (меню Tools). В нем выберете пункт меню File | New | Resource File. В появившемся окошке (Untitled1.res – позже его необходимо будет сохранить под именем DLLRes.res) щелкните правой кнопкой мышки на Contens и выберите New | Bitmap. В появившемся окошке Bitmap Properties будет стоять размер растра по умолчанию – 32×32, пока нажмите OK. Переименуйте Bitmap1 в Bmp1. Выберите в Image Editor File | Open и откройте любую картинку из каталога C:\Program Files\Common Files\Borland Shared\Images\Splash\16Color. Щелкните правой кнопкой мыши на область, свободной от рисунка, и выберите пункт Properties. В данном пункте посмотрите ширину и высоту растра. Закройте данное окно. Теперь откройте BMP1 и, выбрав пункт Properties аналогично описанному ранее способу, проставьте новые размеры. Скопируйте растр из выбранного вами файла в BMP1. Теперь сохраните созданный Вами ресурс (res-файл) под именем DLLRes.res и запишите его в каталог, предназначающийся для проекта библиотеки.

Код DLL-проекта приведите к следующему виду:

library Project1;

uses Windows, Graphics;

{$R DLLRes.res} //Подключение файла ресурсов

//Описание экспортируемой функции, размещаемой в DLL (export)

procedure DrawBMP (Handle: THandle); export; stdcall;

var Bitmap1: TBitmap;

Canvas1: TCanvas;

Begin

//Создаем Bitmap с именем Bitmap класса TBitmap

Bitmap1:= TBitmap.Create;

// Создаем Canvas с именем Canvas класса TCanvas

Canvas1:= TCanvas.Create;

Try

//Растр загружается из ресурсов, идентифицируется именем BMP1

Bitmap1.LoadFromResourceName (HInstance, 'BMP1');

//HInstance снабжает описатель экземпляра или библиотеки для //применения

Canvas1.Handle:= Handle;

Canvas1.Draw(0, 0, Bitmap1); //Помещаем растр на канву

Finally

Canvas1.Free;

//Освобождаем память, зарезервированную под Canvas1

Bitmap1.Free;

//Освобождаем память, зарезервированную под Bitmap1

end;

end;

exports // Список экспортируемых функций

DrawBMP; //Функция у нас единственная – DrawBMP

begin //Блок, соответствующий инициализации библиотеки

End.

В создаваемую библиотеку необходимо подгрузить модули Windows и Graphics. Они необходимы для использования графики в Delphi при помощи Windows-функций.

Аргументом процедуры DrawBMP должен являться идентификатор (Handle) канвы вызываемой формы. У вспомогательного объекта Canvas1 этой процедуры значение Handle устанавливается в значение аргумента процедуры DrawBMP, т.е. Handle, и теперь все его методы будут работать на канве окна, вызывающего функцию приложения.

Создайте DLL, откомпилировав проект (Compile Project Ctrl-F9). Созданная нами библиотека содержит код экспортируемой функции с именем DrawBMP и растровое изображение. Сервер готов.

Статическое связывание

Теперь создадим клиента. Организуйте новый проект, сохраните его в другом каталоге. В используемых модулях допишите еще один – StdCtrls;

В секции implementation введите строку:

procedure DrawBMP (Handle:THandle); stdcall; external 'Project1.dll';

Этим мы декларируем нужную нам функцию. Ключевое слово external указывает, что данная функция размещена в библиотеке с указанным далее именем. Ключевое слово stdcall является директивой и, определяет вызов функции стандартным для операционной системы образом – параметры помещаются в стек слева направо, очистка стека осуществляется вызываемой процедурой. Этот вызов обеспечивает обработку фиксированного числа параметров. При использовании импортируемых функций такие параметры задаются обязательно.

Помимо директивы stdcall существуют и другие директивы вызова:

Register – эта директива используется по умолчанию. Вызов такого типа называется быстрым (fast call). В нем используются три расширенных регистра процессора, в которые помещаются переменные длинной не более 32-х разрядов и указатели. Остальные параметры помещаются в стек слева направо. После использования стек очищается вызываемой процедурой.

Pascal – реализует вызовы в стиле языка Pascal. За очистку стека отвечает вызываемая процедура. Параметры помещаются в стек слева направо. Этот способ вызова является очень быстрым, но не поддерживает переменное число параметров. Используется для поддержки обратной совместимости.

Sdecl – реализует вызовы в стиле языка С. Параметры в стек помещаются справа налево. Очистка стека осуществляется вызывающей процедурой. Такие вызовы обеспечивают обслуживание переменного числа параметров, но скорость обработки меньше, чем в вызовах pascal.

Safecall – параметры помещаются в стек справа налево. Очистка стека осуществляется вызываемой процедурой. Используется в COM и основанных на ней технологиях.

На форме разместите кнопку, в процедуре обработки события щелчка кнопки мыши которой введите строку: DrawBMP(Canvas1.Handle);

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

Delphi позволяет нам писать краткий и удобочитаемый код, но при компиляции этот код преобразуется к вызову массы системных функций (функций API). При этом мы жертвуем размерами и скоростью работы приложений, созданных в Delphi. Если же скорость работы приложения чрезвычайно важна, то можно написать приложение исключительно на функциях API.

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

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

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

Динамическое связывание

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

type //Процедурный тип функции подгружаемой из библиотеки

TDrawBMP = procedure (Handle: THandle); stdcall;

// Обработка события OnClick на кнопке Button1 с надписью BMP

procedure TForm1.Button1Click(Sender: TObject);

Var

hcDll: THandle; //Указатель на библиотеку

DrawBMP: TDrawBMP; //Подгружаемая функция

Begin

hcDll:= LoadLibrary('Project1.dll'); //Динамическая загрузка DLL

if hcDll <= HINSTANCE_ERROR then begin //Загрузка не удалась

MessageDlg ('Отсутствует библиотека Project1.dll!', mtError, [mbOK], 0);

Exit;

end;

//Библиотека загружена. Получаем адрес точки входа нужной функции

DrawBMP:= GetProcAddress(hCDll, 'DrawBMP');

//Проверка на успешность связывания

if not Assigned (DrawBMP) then

Begin



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: