Шрифт:
Интервал:
Закладка:
Главное в рассмотренном примере заключается в том, что код приложения не содержит напрямую ничего, связанного с отображаемой в окне картинкой. Приложение обращается к указанной нами библиотеке динамической компоновки, которая выполняет всю работу по выводу изображения.
Первый наш пример является моделью диалога приложения с библиотеками вообще. Каждый раз, когда нам это необходимо, работает библиотека, путем вызова нужной функции.
Посмотрим внимательнее на работу приложения. Картинка исчезает при каждой перерисовке окна, например, если минимизировать, а затем восстановить окно, то картинка "пропадет". Объяснить это легко: при перерисовке окна вызывается собственный обработчик события Onpaint окна, а мы позаботились о наличии в нем кода, с помощью которого можно было бы запоминать текущий вид окна. Операционная система подобную услугу не предоставляет, поскольку на нее требуется слишком много ресурсов. Шлифовать код этого примера не станем, мы получили от него почти все, что требовалось для нас.
Запустите несколько копий клиентов и протестируйте вывод картинки на поверхность каждого из них. Пример упрощенный, но я, надеюсь, он смог достичь главной цели, преследуемой мною. Использование динамических библиотек является действительно эффективной технологией построения архитектуры программных систем: код клиентов освобожден от дублирования.
Еще одно важное свойство динамических библиотек состоит в том, что при их использовании безразлично, в какой программной системе созданы клиенты и сами библиотеки. Этим мы пользуемся во время применения DirectX в проектах Delphi точно так же, как и при использовании любой системной библиотеки.
В коде клиента указывается имя вызываемой функции, но во время работы откомпилированного приложения клиент при вызове динамической библиотеки ориентируется не по имени функции, а по соответствующей функции точке входа, адрес которой он получает при инициализации библиотеки. Взгляните снова на рис. 1.1. Слева от имени экспортируемой функции вы найдете адрес точки входа. Клиент при инициализации библиотеки получает это значение в качестве опорного для вызова функции.
Вспомним, что при запуске исполнимого модуля клиента происходит исключение при отсутствии необходимой библиотеки, рассмотренная компоновка приложения называется статическим связыванием.
Динамическое связывание отличается тем, что клиент загружает библиотеку не сразу же после своего размещения в памяти, т. е. запуска, а по мере надобности. Примером такого подхода является проект каталога Ех03. В разделе implementation модуля записано следующее:
type // Процедурный тип функции, подгружаемой из библиотеки
TDrawBMP = procedure (Handle : THandle); stdcall; // Щелчок кнопки с надписью BMP
procedure TForml.ButtonlClick(Sender: TObject); var
hcDll : THandle; // Указатель на библиотеку
procDrawBMP : TDrawBMP; // Подгружаемая функция
begin
hcDll := LoadLibrary('Projectl.dll'); // Динамическая загрузка DLL if hcDll <= HINSTANCE_ERROR then begin // Загрузка не удалась
MessageDlg ('Отсутствует библиотека Projectl!', mtError, [mbOK], 0) ; Exit;
end;
// Библиотека загружена. Получаем адрес точки входа нужной функции procDrawBMP := GetProcAddress(hCDll, 'DrawBMP');
// проверка на успешность операции связывания if not Assigned (procDrawBMP) then begin
MessageDlg (В библиотеке Projectl.dll отсутствует нужная функция!,
mtError, [mbOK], 0); Exit;
end;
procDrawBMP (Canvas.Handle); // Вызываем функцию
FreeLibrary(hcDll); // Выгружаем библиотеку
end;
Схема наших действий теперь такова: загружаем библиотеку только в момент, когда она действительно необходима, получаем адрес требуемой функции и обращаемся к ней. Обратите внимание, что успешная загрузка
библиотеки не является окончательным признаком того, что мы можем успешно использовать необходимую нам функцию. В каталог этого проекта автор поместил "испорченную" библиотеку Projectl.dll, в ней отсутствует нужная нам функция.
Подобная ситуация на практике вполне возможна, если у одной и той же библиотеки есть несколько версий, различающихся набором функций. Производитель подчас распространяет несколько версий программы, различающихся функциональностью, и использующие их клиенты должны перед вызовом функций производить проверку на действительное присутствие этих функций в библиотеке.
Протестируйте работу проекта, заменив библиотеку в его каталоге "правильной", из каталога самого первого примера.
Динамическая загрузка библиотек используется знакомыми вам приложениями очень часто. Например, при проверке правописания текстовый редактор загружает соответствующую библиотеку только при установленном режиме проверки.
СОМ-модель
Технология, основанная на динамических библиотеках, является очень эффективной, потому и стала основой программной архитектуры операционной системы. Однако ей присуще ограничение, не позволяющее использовать парадигму объектно-ориентированного программирования (ООП): библиотеки могут содержать код функций и процедур, а также ресурсы, но не способны содержать описания классов. Это утверждение верно отчасти, я говорю пока о DLL "в чистом виде". По мере развития программирования как технологии, возникла необходимость поддержки ООП на уровне операционной системы.
Самым ходовым примером такого использования идей ООП на уровне операционной являются составные документы. Вставляя в текстовый документ электронную таблицу или записывая в нем математическую формулу с помощью редактора формул, пользователь текстового процессора как раз встречается со зримым воплощением ООП. Вставленный, внедренный документ является объектом со своими свойствами и методами. Это пример зримого воплощения технологии COM (Component Object Model, модель компонентных объектов). Хотя я и упомянул в примере составные документы, СОМ предоставляет концепцию взаимодействия программ любых типов: библиотек, приложений, системного программного обеспечения и др. Для нашей темы важно подчеркнуть, что СОМ стала частью технологий, не имеющих никакого отношения к составным документам.
СОМ может применяться для создания программ любых типов, в частности DirectX использует эту технологию. Поэтому мы и вынуждены сделать небольшой экскурс в эту тему.
Первоначально для всей группы технологий, в основе которых лежит СОМ, корпорацией Microsoft было предложено общее имя - OLE. Затем, по мере развития и дополнения технологии, это название менялось. Например, однажды оно стало ActiveX, но программисты со стажем часто так и продолжают пользоваться термином OLE (сейчас это не является аббревиатурой) для обозначения данной группы технологий.
СОМ - не язык, не протокол. Это метод взаимодействия между программами и способ создания программ.
функции программы, доступные для использования другим программам, называются сервисами. СОМ определяет стандартный механизм, с помощью которого одна часть программного обеспечения предоставляет свои сервисы другой.
Для нас особенно важно то, что технология СОМ также является независимой от языка программирования. Физически приложение, предоставляющее сервисы, может быть реализовано в виде обычного выполнимого модуля, либо, чаще всего, реализовано в виде библиотеки. Как и в случае обычных библиотек, неважно, в какой программной системе созданы серверы и использующие их клиенты. В случае с обычной DLL-библиотекой клиенту достаточно знать адрес точки входа нужной функции и в определенный момент передать управление по этому адресу. Тот факт, что библиотека должна предоставлять не обычные функции, а методы объектов, внес в эту схему некоторые изменения, о которых мы поговорим позже.
Контроль версии
Сервером может быть целый программный комплекс, а не один-единственный файл.
При распространении библиотеки ее обычно помещают в какой-либо общедоступный каталог, например системный. Это вам знакомо, поскольку встречалось при установке программ. Наверняка вам известны и возникающие при этом проблемы. Например, при самостоятельном удалении таких программ сопутствующие библиотеки могут остаться, хотя больше никто их не использует.
Если же сервер представляет собой не один файл, а внушительный набор модулей, то размещение его целиком в системном каталоге принесло бы массу дополнительных проблем пользователю, который не сможет правильно определить назначение каждого файла из десятка установленных в системном каталоге.
Перед разработчиками операционной системы стояла следующая задача: необходимо предоставить клиенту возможность доступа к серверу независимо от места его физического расположения. Пусть пользователь устанавливает программы там, где это ему необходимо, хоть и не в общедоступном каталоге, а клиентские программы должны получать доступ к серверу, где бы он ни располагался.
Один из способов решения задачи таков: при установке программы в файл автозагрузки дописывается строка, объявляющая каталог устанавливаемой программы доступным для всех приложений. Теперь при каждом поиске файла система будет заглядывать и в этот каталог. Подобное решение малоэффективно и удовлетворительным являлось лишь два десятилетия назад, когда на одном компьютере установить больше десятка крупных программ практически было невозможно. Сегодня же на компьютере пользователя могут быть установлены одновременно сотни приложений, и блуждание по каталогам может оказаться чересчур долгим. К тому же библиотеки разных производителей, с различным набором функций, могут быть случайно названы одинаково, и клиенту первым может попасться не тот сервер, который он ищет.
- Delphi. Учимся на примерах - Сергей Парижский - Программирование
- C++ - Страустрап Бьярн - Программирование
- PHP. Разработка модуля комментариев для сайта - Дмитрий Приходько - Прочая околокомпьтерная литература / Программирование