Работа с библиотеками DDE и DLL в Delphi

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

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 03.03.2018
Размер файла 105,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

Работа с библиотеками DDE и DLL в Delphi

1. Библиотека управления динамическим обменом данными (DDE) в Delphi

1.1 Понятие DDE и использование в Delphi

Аббревиатура DDEML обозначает Dynamic Data Exchange Management Library (библиотека управления динамическим обменом данными). DDEML это надстройка над сложной системой сообщений, называемой Dynamic Data Exchange (DDE). Библиотека, содержащая DDE, была разработана для усиления возможностей первоначальной системы сообщений Windows.

DDE дает возможность перейти через рамки приложения и взаимодействовать с другими приложениями и системами Windows.

Dynamic Data Exchange получило свое имя потому, что позволяет двум приложениям обмениваться данными (текстовыми, через глобальную память) динамически во время выполнения. Связь между двумя программами можно установить таким образом, что изменения в одном приложении будут отражаться во втором. Например, если Вы меняете число в электронной таблице, то во втором приложении данные обновятся автоматически и отобразят изменения. Кроме того, с помощью DDE можно из своего приложения управлять другими приложениями, такими, как Word for Windows, Report Smith, Excel и др.

Приложение, получающее данные из другого приложения по DDE и/или управляющее другим приложением с помощью команд через DDE является DDE-клиентом. В этом случае второе приложение является DDE-сервером. Одно и то-же приложение может быть одновременно и сервером, и клиентом (например, MicroSoft Word). Построение DDE-серверов и DDE-клиентов удобно рассмотреть на примере, поставляемом с Delphi (каталог x:\delphi\demos\ddedemo). Сперва давайте рассмотрим логику работы примера. Для начала нужно откомпилировать проекты DDESRVR.DPR и DDECLI.DPR, после этого запустите программу DDECLI.EXE (DDE-клиент) и выберите пункт меню File|New Link. При этом должна запуститься программа DDESRVR (DDE-сервер). Если теперь редактировать текст в окне сервера, то изменения мгновенно отразятся в приложении-клиенте (см. рис.1, 2)

Рис.1. Приложение - DDE-сервер. Здесь идет редактиро-вание текста.

Рис.2. Приложение - DDE-клиент. Здесь отображаются изменения.

Пример демонстрирует и другие возможности DDE: пересылка данных из клиента на сервер (Poke Data); наберите любой текст в правом окне DDE-клиента и нажмите кнопку Poke Data, этот текст появится в окне сервера.

- исполнение команд (макросов) на сервере; наберите любой текст в правом окне DDE-клиента и нажмите кнопку Exec Macro, DDE-сервер выдаст соответствующее диалоговое окно.

- установление связи через Clipboard; закройте оба DDE-приложения и запустите их заново, затем в DDE-сервере выберите пункт меню Edit|Copy, далее в клиенте выберите пункт меню Edit|Paste Link.

Теперь давайте рассмотрим эти демонстрационные программы с технической точки зрения и узнаем, каким образом в Delphi можно создать DDE-приложения. Начнем с DDE-сервера.

1.2 DDE-серверы

На рис.3 представлен пример DDE-сервера во время дизайна в среде Delphi.

Рис.3. DDE-сервер в среде Delphi.

Для построении DDE-сервера в Delphi имеются два объекта, расположенные на странице System Палитры Компонент - TDdeServerConv и TDdeServerItem. Обычно в проекте используется один объект TDdeServerConv и один или более TDdeServerItem. Для получения доступа к сервису DDE-сервера, клиенту потребуется знать несколько параметров : имя сервиса (Service Name) - это имя приложения (обычно - имя выполняемого файла без расширения EXE, возможно с полным путем); Topic Name - в Delphi это имя компоненты TDdeServerConv; Item Name - в Delphi это имя нужной компоненты TDdeServerItem.

Назначение объекта TDdeServerConv - общее управление DDE и обработка запросов от клиентов на выполнение макроса. Последнее выполняется в обработчике события OnExecuteMacro, например, как это сделано в нашем случае:

procedure TDdeSrvrForm.doMacro(Sender: TObject;

Msg: TStrings);

var

Text: string;

begin

Text := '';

if Msg.Count > 0 then Text := Msg.Strings[0];

MessageDlg ('Executing Macro - ' + Text, mtInformation,

[mbOK], 0);

end;

Объект TDdeServerItem связывается с TDdeServerConv и определяет, что, собственно, будет пересылаться по DDE. Для этого у него есть свойства Text и Lines. (Text имеет то же значение, что и Lines[0].) При изменении значения этих свойств автоматически происходит пересылка обновленных данных во все приложения-клиенты, установившие связь с сервером. В нашем приложении

Изменение значения свойства Lines происходит в обработчике события OnChange компонента Edit1:

procedure TDdeSrvrForm.doOnChange(Sender: TObject);

begin

if not FInPoke then

DdeTestItem.Lines := Edit1.Lines;

end;

Этот же компонент отвечает за получение данных от клиента, в нашем примере это происходило при нажатии кнопки Poke Data, это выполняется в обработчике события OnPokeData:

procedure TDdeSrvrForm.doOnPoke(Sender: TObject);

begin

FInPoke := True;

Edit1.Lines := DdeTestItem.Lines;

FInPoke := False;

end;

И последнее - для установление связи через Clipboard служит метод CopyToClipboard объекта TDdeServerItem. Необходимая информация помещается в Clipboard и может быть вызвана из приложения-клиента при установлении связи. Обычно в DDE-серверах для этого есть специальный пункт меню Paste Special или Paste Link.

Итак, мы рассмотрели пример полнофункционального DDE-сервера, построенного с помощью компонентов Delphi. Весьма часто существующие DDE-серверы неполностью реализуют возможности DDE и предоставляют только часть сервиса. Например, ReportSmith позволяет по DDE только выполнять команды (макросы).

1.3 DDE-клиенты

На рис.4 представлен пример DDE-клиента во время дизайна в среде Delphi.

Рис.4. DDE-клиент в среде Delphi.

Для построения DDE-клиента в Delphi используются два компонента: TDDEClientConv и TDDEClientItem. Аналогично серверу, в программе обычно используются один объект TDDEClientConv и один и более связанный ним TDDEClientItem.

TDDEClientConv служит для установления связи с сервером и общим управлением DDE-связью. Установить связь с DDE-сервером можно как в процессе дизайна, так и во время выполнения программы, причем двумя способами. Первый способ - заполнить вручную необходимые свойства компонента: это DdeService, DdeTopic и ServiceApplication. Во время дизайна щелкните дважды на одно из первых двух свойств в Инспекторе Объектов - Вы получите диалог для определения DDE-связи (см. рис.5).

Рис.5. Диалог для установления связи с DDE-сервером (Report Smith).

Укажите в диалоге имена DDE Service и DDE Topic. Их можно узнать из документации по тому DDE-серверу, с которым Вы работаете. В случае DDE-сервера, созданного на Delphi, это имя программы (без .EXE) и имя объекта TDdeServerConv. Для установления связи через Clipboard в диалоге есть специальная кнопка Past Link. Ею можно воспользоваться, если Вы запустили DDE-сервер, сохранили каким-то образом информацию о связи и вошли в этот диалог. Например, если DDE-сервером является DataBase Desktop, то нужно загрузить в него какую-нибудь таблицу Paradox, выбрать любое поле и пункт меню Edit|Copy. После этого войдите в диалог и нажмите кнопку Paste Link. Поля в диалоге заполнятся соответствующим образом.

Свойство ServiceApplication заполняется в том случае, если в поле DDEService содержится имя, отличное от имени программы, либо если эта программа не находится в текущей директории. В данном поле указываются полный путь и имя программы без расширения (.EXE). При работе с Report Smith здесь нужно указать, например : C:\RPTSMITH\RPTSMITH

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

В нашей демо-программе связь устанавливается во время выполнения программы в пунктах меню File|New Link и Edit|Paste Link. В пункте меню File|New Link программно устанавливается связь по DDE с помощью соответствующего метода объекта TDdeServerConv, OpenLink делать не надо, поскольку свойство ConnectMode имеет значение ddeAutomatic:

procedure TFormD.doNewLink(Sender: TObject);

begin

DdeClient.SetLink(AppName.Text, TopicName.Text);

DdeClientItem.DdeConv := DdeClient;

DdeClientItem.DdeItem := ItemName.Text;

end;

Здесь же заполняются свойства объекта TDdeClietItem.

В пункте меню Edit|Past Link программно устанавливается связь по DDE с использованием информации из Clipboard:

procedure TFormD.doPasteLink(Sender: TObject);

var

Service, Topic, Item : String;

begin

if GetPasteLinkInfo (Service, Topic, Item) then

begin

AppName.Text := Service;

TopicName.Text := Topic;

ItemName.Text := Item;

DdeClient.SetLink (Service, Topic);

DdeClientItem.DdeConv := DdeClient;

DdeClientItem.DdeItem := ItemName.Text;

end;

end;

После того, как установлена связь, нужно позаботиться о поступающих по DDE данных, это делается в обработчике события OnChange объекта TDdeClietItem:

procedure TFormD.DdeClientItemChange(Sender: TObject);

begin

DdeDat.Lines := DdeClientItem.Lines;

end;

Это единственная задача объекта TDdeClientItem.

На объект TDdeClientConv возлагаются еще две задачи : пересылка данных на сервер и выполнение макросов, для чего у данного объекта имеются соответствующие методы. Посмотрим, как это можно было бы сделать. Выполнение макроса на сервере:

procedure TFormD.doMacro(Sender: TObject);

begin

DdeClient.ExecuteMacroLines(XEdit.Lines, True);

end;

Пересылка данных на сервер:

procedure TFormD.doPoke (Sender: TObject);

begin

DdeClient.PokeDataLines(DdeClientItem.DdeItem,XEdit.Lines);

end;

Управление ReportSmith по DDE

В прилагаемом примере run-time версия ReportSmith выполняет команду, переданную по DDE. Имена DDE сервиса для ReportSmith и некоторых других приложений можно узнать в Справочнике в среде ReportSmith.

Перед запуском примера следует правильно установить в свойстве ServiceApplication путь к run-time версии ReportSmith и в тексте программы в строке

Cmd:='LoadReport "c:\d\r\video\summary.rpt","@Repvar1=<40>,@Repvar2=<'#39'Smith'#39'>"'#0;

правильно указать путь к отчету.

2. Работа с динамически подсоединяемыми библиотеками (dynamic link libraries - DLL) в Delphi

2.1 Понятие DLL

Вспомним процесс программирования в DOS. Преобразование исходного текста программы в машинный код включал в себя два процесса - компиляцию и линковку. В процессе линковки редактор связей, компоновавший отдельные модули программы, помещал в код программы не только объявления функций и процедур, но и их полный код. Вы готовили, таким образом, одну программу, другую, третью ... И везде код одних и тех же функций помещался в программу полностью (см. рис 1).

Размещено на http://www.allbest.ru/

Рис.1 Вызов функций при использовании статической компоновки

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

Размещено на http://www.allbest.ru/

Рис. 2. Вызов функций при использовании динамической компоновки.

Но чем же отличаются Dynamic Link Library (DLL) от обычных приложений? Для понимания этого требуется уточнить понятия задачи (task), экземпляра (копии) приложения (instance) и модуля (module).

При запуске нескольких экземпляров одного приложения Windows загружает в оперативную память только одну копию кода и ресурсов - модуль приложения, создавая несколько отдельных сегментов данных, стека и очереди сообщений (см. рис. 3), каждый набор которых представляет собой задачу в понимании Windows. Копия приложения представляет собой контекст, в котором выполняется модуль приложения.

Рис.3. Копии и модуль приложения.

DLL - библиотека также является модулем. Она находится в памяти в единственном экземпляре и содержит сегмент кода и ресурсы, а также сегмент данных (см. рис. 4).

Рис.4. Структура DLL в памяти.

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

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

Часто, в виде DLL создаются отдельные наборы функций, объединенные по тем или иным логическим признакам, аналогично тому, как концептуально происходит планирование модулей ( в смысле unit ) в Pascal. Отличие заключается в том, что функции из модулей Pascal компонуются статически - на этапе линковки, а функции из DLL компонуются динамически, то есть в run-time.

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

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

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

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

Screen.Cursors[myCursor] := LoadCursor(HInstance, MYCURSOR');

LoadCursor - функция Windows API, которая вызывается приложением из динамической библиотеки User 32.dll. Кстати, примером хранимых в динамической библиотеке ресурсов могут являться такие стандартные диалоги Windows, как диалог открытия файла, печати или настройки принтера, которые находятся в файле Comctl32.dll. Однако многие прикладные разработчики используют функции вызова форм этих диалогов, совершенно не задумываясь, где хранится их описание. Второй тип процедур - это те, которые используются только внутри самого файла библиотеки.

2.2 Основные преимущества использования DLL

Применение DLL имеет множество положительных моментов.

Во-первых, это повторное использование кода. Думаем, нет необходимости пояснять удобство использования один раз разработанных процедур и функций при создании нескольких приложений. Кроме того, имеется возможность использовать некоторые из своих библиотек, не раскрывая исходных кодов. Чем тогда это лучше компонентов? Тем, что функции, хранящиеся в библиотеке, могут быть вызваны на выполнение из приложений, разработанных не на Object Pascal, а, например, с использованием C++Builder, Visual Basic, Visual C++ и т.д. Такой подход накладывает некоторые ограничения на принцип разработки библиотеки, но это возможно.

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

В-третьих, следует поговорить вот о чем. Всего несколько лет назад при разработке программного обеспечения вы могли совершенно не волноваться по поводу распространения ваших продуктов где-либо, кроме вашей страны. Хотим сказать, что проблема перевода на другие языки текста на элементах управления (пункты меню, кнопки, выпадающие списки, подсказки), сообщений об ошибках и т.д. не стояла так остро, как сейчас. Однако, с повсеместным внедрением Интернета у пользователей появилась возможность быстрой передачи готовых программных продуктов практически в любую точку мира. И что будут делать с вашей программой где-нибудь в Объединенных Арабских Эмиратах, если кроме как по-русски, она с пользователем общаться не умеет? Вы сами можете оценить этот эффект, если хоть раз на экране вашего компьютера вместо с детства знакомого русского языка появится "арабская вязь" (например, из-за "сбоя" шрифтов). Итак, уже сейчас вы должны планировать возможность распространения ваших приложений в других странах (если, конечно, у вас есть желание получить как можно больше прибыли). Соответственно, встает вопрос быстрого перевода интерфейса вашей программы на другие языки. Одним из путей может являться создание ресурсов интерфейсов внутри DLL. К примеру, можно создать одно приложение, которое в зависимости от версии динамической библиотеки, будет выводить сообщения на различных языках.

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

2.3 Основы разработки DLL

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

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

library MyFirstDLL;

uses

SysUtils,

Classes,

Forms,

Windows;

procedure HelloWorld(AForm : TForm);

begin

MessageBox(AForm.Handle, Hello world!',

DLL Message Box', MB_OK or MB_ICONEXCLAMATION);

end;

exports

HelloWorld;

begin

end.

Первое, на что следует обратить внимание, это ключевое слово library, находящееся вверху страницы. Library определяет этот модуль как модуль библиотеки DLL. Далее идет название библиотеки. В нашем примере мы имеем дело с динамической библиотекой, содержащей единственную процедуру: HelloWorld. Причем обратите внимание, что данная процедура по структуре ничем не отличается от тех, которые вы помещаете в модули своих приложений. Ключевое слово exports сигнализирует компилятору о том, что перечисленные ниже функции и/или процедуры должны быть доступны из вызывающих приложений (т.е. они как бы "экспортируются" из библиотеки).

И, наконец, в конце модуля можно увидеть ключевые слова begin и end. Внутри данного блока вы можете поместить код, который должен выполняться в процессе загрузки библиотеки. Достаточно часто этот блок остается пустым. delphi сервер связь библиотека

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

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

В дополнение к процедурам и функциям, DLL может содержать глобальные данные, доступ к которым разрешен для всех процедур и функций в библиотеке. Для 16-битных приложений эти данные существовали в единственном экземпляре независимо от количества загруженных в оперативную память программ, которые используют текущую библиотеку. Иными словами, если одна программа изменяет значение глобальной переменной a на 100, то для всех остальных приложений a будет значение 100. Для 32-битных приложений это не так. Теперь для каждого приложения создается отдельная копия глобальной области данных.

2.4 Экспорт функций из DLL

Как уже отмечалось выше, для экспорта процедур и функций из DLL необходимо использовать ключевое слово export. Еще раз обратите внимание на представленный выше листинг библиотеки MiFirstDll. Поскольку процедура HelloWorld определена как экспортируемая, то она может быть вызвана на выполнение из других библиотек или приложений. Существуют следующие способы экспорта процедур и функций: экспорт по имени и порядковому номеру.

Наиболее распространенный способ экспорта - по имени. Взглянем на приведенный ниже текст:

exports

SayHello,

DoSomething,

DoSomethingReallyCool;

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

Для того, чтобы определить выполняется ли ваш кодек в DLL или вызывающем приложении, можно воспользоваться глобальной переменной IsLibrary. Она принимает значение true в том случае, если код вызывается из библиотеки и false в случае выполнения процедуры или функции из вызывающего приложения.

Кроме того, в поставку Delphi входит весьма полезная утилита tdump, которая предоставляет данные о том, какая информация экспортируется из указанной DLL.

2.5 Использование DLLProc

Как уже отмечалось, код инициализации динамической библиотеки может быть помещен в блок begin...end. Однако, кроме того зачастую необходимо предусмотреть некоторые действия, выполняемые в процессе выгрузки DLL из оперативной памяти. В отличие от других типов модулей, модуль DLL не имеет секции initialization или finalization. К примеру, вы можете динамически выделить память в главном блоке, однако непонятно, где эта память должна быть освобождена. Для решения данной проблемы существует DLLProc - специальная процедура, вызываемая в определенные моменты функционирования DLL.

Для начала следует сказать о самой причине существования DLLProc. Динамическая библиотека получает сообщения от Windows в моменты своей загрузки и выгрузки из оперативной памяти, а также в тех случаях, когда какой-нибудь очередной процесс, использующий функции и/или ресурсы, хранящиеся в библиотеке, загружается в память. Такая ситуация возможна в том случае, когда библиотека необходима для функционирования нескольких приложений. А для того, чтобы иметь возможность указывать, что именно должно происходить в такие моменты, необходимо описать специальную процедуру, которая и будет ответственна за такие действия. К примеру, она может выглядеть следующим образом:

procedure MyFirstDLLProc(Reason: Integer);

begin

if Reason = DLL_PROCESS_DETACH then

{DLL is unloading. Cleanup code here.}

end;

Однако системе совершенно неочевидно, что именно процедура MyFirstDllProc ответственна за обработку рассмотренных выше ситуаций. Поэтому нужно поставить в соответствие адрес нашей процедуры глобальной переменной DLLProc. Это необходимо сделать в блоке begin...end примерно так:

begin

DLLProc := @MyDLLProc;

{ Что-нибудь еще, что должно выполняться в

процессе инициализации библиотеки }

end.

Ниже представлен код, демонстрирующий один из возможных вариантов применения DLLProc.

library MyFirstDLL;

uses

SysUtils,

Classes,

Forms,

Windows;

var

SomeBuffer : Pointer;

procedure MyFirstDLLProc(Reason: Integer);

begin

if Reason = DLL_PROCESS_DETACH then

{DLL is выгружается из памяти.

Освобождаем память, выделенную под буфер.}

FreeMem(SomeBuffer);

end;

procedure HelloWorld(AForm : TForm);

begin

MessageBox(AForm.Handle, Hello world!',

DLL Message Box', MB_OK or MB_ICONEXCLAMATION);

end;

{Какой-нибудь код, в котором используется SomeBuffer.}

exports

HelloWorld;

begin

{Ставим в соответствие с переменной

DLLProc адрес нашей процедуры.}

DLLProc := @MyFirstDLLProc;

SomeBuffer := AllocMem(1024);

end.

Как из этого явствует, в качестве признака того или иного события, в результате которого вызывается процедура MyFirstDll, является значение переменной Reason. Ниже приведены возможные значения данной переменной.

DLL_PROCESS_DETACH - библиотека выгружается из памяти; используется один раз;

DLL_THREAD_ATTACH - в оперативную память загружается новый процесс, использующий ресурсы и/или код из данной библиотеки;

DLL_THREAD_DETACH - один из процессов, использующих библиотеку, "выгружается" из памяти.

2.6 Загрузка DLL

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

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

Смысл динамического метода заключается в том, что пользователь загружает библиотеку не при старте приложения, а в тот момент, когда это действительно необходимо. Естественно, ведь если функция, описанная в динамической библиотеке, используется только при 10% запусков программы, то совершенно не имеет смысла применить статический метод загрузки. Выгрузка библиотеки из памяти в данном случае также осуществляется под контролем пользователя. Еще одно преимущество такого способа загрузки DLL - это уменьшение (по понятным причинам) времени старта приложения пользователя. Какие же у этого способа имеются недостатки? Основной - это то, что использование данного метода является более хлопотным, чем рассмотренная выше статическая загрузка. Сначала необходимо воспользоваться функцией Windows API LoadLibrary. Для получения указателя на экспортируемой процедуры или функции должна использоваться функция GetProcAddress. После завершения использования библиотеки DLL должна быть выгружена с применением FreeLibrary.

2.7 Вызов процедур и функций, загруженных из DLL

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

Вызов функций и процедур из статически загруженных DLL достаточно прост. Первоначально в приложении должно содержаться описание экспортируемой функции (процедуры). После этого можно их использовать точно так же, как если бы они были описаны в одном из модулей приложения пользователя. Для импорта функции или процедуры, содержащейся в DLL, необходимо использовать модификатор external в их объявлении. К примеру, для рассмотренной нами выше процедуры HelloWorld в вызывающем приложении должна быть помещена следующая строка:

procedure SayHello(AForm : TForm); external myfirstdll.dll';

Ключевое слово external сообщает компилятору, что данная процедура может быть найдена в динамической библиотеке (в нашем случае - myfirstdll.dll). Далее вызов этой процедуры выглядит следующим образом:

...

HelloWorld(self);

...

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

Импорт из DLL может проводиться по имени процедуры (функции), порядковому номеру или с присвоением другого имени.

В первом случае просто объявляется имя процедуры и библиотеки, из которой ее импортируете (мы это рассмотрели чуть выше). Импорт по порядковому номеру требует от пользователя указание самого этого номера:

procedure HelloWorld(AForm : TForm);

external myfirstdll.dll' index 15;

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

Если вы по каким-то причинам не применяете описанный выше способ импорта, но, тем не менее, хотите изменить имя импортируемой функции (процедуры), то можно воспользоваться третьим методом:

procedure CoolProcedure;

external myfirstdll.dll' name DoSomethingReallyCool';

Здесь импортируемой процедуре CoolProcedure дается имя DoSomethingReallyCool. Вызов процедур и функций, импортируемых из динамически загружаемых библиотек, несколько более сложен, чем рассмотренный нами выше способ. В данном случае требуется объявить указатель на функцию или процедуру, которую далее собираетесь использовать. Помните процедуру HelloWorld? Давайте посмотрим, что необходимо сделать для того, чтобы вызвать ее на выполнение в случае динамической загрузки DLL. Во-первых, необходимо объявить тип, который описывал бы эту процедуру:

type

THelloWorld = procedure(AForm : TForm);

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

var

DLLInstance : THandle;

HelloWorld : THelloWorld;

begin

{ загружаем DLL }

DLLInstance := LoadLibrary(myfirstdll.dll');

{ получаем указатель }

@HelloWorld := GetProcAddress(DLLInstance, HelloWorld');

{ вызываем процедуру на выполнение }

HelloWorld(Self);

{ выгружаем DLL из оперативной памяти }

FreeLibrary(DLLInstance);

end;

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

procedure TForm1.DynamicLoadBtnClick(Sender: TObject);

type

THelloWorld = procedure(AForm : TForm);

var

DLLInstance : THandle;

HelloWorld : THelloWorld;

begin

DLLInstance := LoadLibrary(myfirstdll.dll');

if DLLInstance = 0 then begin

MessageDlg(Невозможно загрузить DLL', mtError, [mbOK], 0);

Exit;

end;

@HelloWorld := GetProcAddress(DLLInstance, HelloWorld');

if @HelloWorld <> nil then

HelloWorld (Self)

else

MessageDlg(Не найдена искомая процедура!.', mtError, [mbOK], 0);

FreeLibrary(DLLInstance);

end;

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

Разработку DLL, содержащую форму, рассмотрим на примере.

Создадим, прежде, новый проект динамической библиотеки. Для этого выберем пункт меню File|New, а затем дважды щелкнем на иконку DLL. После этого можно увидеть примерно следующий код:

library Project2;

{здесь были комментарии}

uses

SysUtils,

Classes;

{$R *.RES}

begin

end.

Сохраним полученный проект. Назовем его DllForms.dpr.

Теперь следует создать новую форму. Это можно сделать по-разному. Например, выбрав пункт меню File|New Form. Добавим на форму какие-нибудь компоненты. Назовем форму DllForm и сохраним получившийся модуль под именем DllFormUnit.pas.

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

function ShowForm : Integer

Краткие выводы

DDE (Dynamic Data Exchange - DDE) - библиотека управления динамическим обменом данными была разработана для усиления возможностей первоначальной системы сообщений Windows.

Приложение, получающее данные из другого приложения по DDE и/или управляющее другим приложением с помощью команд через DDE, является DDE - клиентом.

DLL (Dynamic Link Library) библиотека, в отличие от приложения, не имеет ни стека, ни очереди сообщений. Функции, помещенные в DLL, выполняются в контексте вызвавшего приложения, пользуясь его стеком. Но эти же функции используют сегмент данных, принадлежащий библиотеке, а не копии приложения.

Ключевые слова

Реализация классов, задача (task), экземпляр (копия), приложение (instance), модуль (module), DLL- экспорт, DLL- импорт, сервер, клиент, DDE - сервер, DDE - клиент.

Вопросы для самоконтроля

1. Для чего используется DDE в Delphi?

2. Что подразумевается под понятием DDE - сервер?

3. Что подразумевается под понятием DDE - клиент?

4. В чем заключается процесс создания DLL в Delphi (экспорт)?

5. Какова суть использования DLL в Delphi (импорт)?

Рекомендуемая литература

1. Архангельский А. Программирование в Delphi 7. - М.: ООО «Бином - Пресс», 2004. -1152с.

2. 2.Брауде Э. Технология разработки программного обеспечения. Питер - 2004. - 325 с.

3. 3.Бобров И.С. Delphi 7. Учебный курс. Москва. Санкт-Петербург, Нижний Новгород, Воронеж, Питер.- 2003.- 625

4. Гради Буч. Объектно-ориентированный анализ и проектирование с примерами приложений на С++. Бином · 1998.

5. Джон Влиссидес, Эрих Гамма, Ричард Хелм, Ральф Джонсон. Приемы объектно-ориентированного проектирования. Паттерны проектирования. - Питер. 2003. - 256 с.

6. Иванова Г.С., Ничушкина Т.Н., Пугачев Е.К. Объектно-ориентированное программирование. - М.: Изд. МГТУ имени Н.Э. Баумана. 2003.- 320с.

7. Кьоу Дж., Джеанини М.Объектно-ориентированное программирование. Просто и понятно. ? М.: Питер, 2005. -403с.

8. Лесневский А.С. Объектно-ориентированное программирование для начинающих. - М.: Бином. Лаборатория знаний. 2005. - 382 с.

9. Синтес Антони. Освой самостоятельно объектно-ориентированное программирование за 21 день. Просто и понятно? М.: Вильямс. 2002. -284с.

10. http://www.iite - сайт ЮНЕСКО «Информационные технологии в образовании».

11. http://.borland.com/delphi_net/ - Официальный сайт Borland Delphi

12. http://delphin.xost.ru/ - сайт помощи для программирования в среде Delphi.

Размещено на Allbest.ru


Подобные документы

  • Основные приемы работы в среде программирования Delphi. Особенности технологии создания простейших приложений. Работа с компонентами среды разработки приложений. Ввод, редактирование, выбор и вывод информации. Аспекты использования структуры ветвления.

    методичка [619,9 K], добавлен 17.11.2011

  • Delphi как среда разработки программ, ориентированных на работу в Windows. Назначение и преимущество использования электронных учебников. Описание возможностей среды Delphi 5 для разработки электронного учебника. Варианты применения служб Internet.

    дипломная работа [3,6 M], добавлен 13.07.2011

  • Теоретические основы применения технологии ADO в среде Delphi. Основные понятия и определения теории баз данных. Компоненты Delphi для создания приложений, оперирующих с базами данных. Общий вид и основные особенности работы приложения "Аптека".

    курсовая работа [1,4 M], добавлен 09.08.2012

  • Особенности среды визуального проектирования Borland Delphi 7.0. Этапы разработки программы и составления блок-схемы алгоритмов. Способы вычисления кусочно-заданной функции одной переменной. Рассмотрение компонентов среды Delphi, ее предназначение.

    контрольная работа [703,8 K], добавлен 24.09.2012

  • Интегрированная среда разработки Delphi и элементы, входящие в ее состав. Математическая модель, алгоритм решения и его свойства. Описание операторов, процедур, функций и методов. Создание приложений по аналитической геометрии и теоретической механике.

    курсовая работа [1,8 M], добавлен 26.05.2010

  • Delphi - среда быстрой разработки, в которой в качестве языка программирования используется типизированный объектно-ориентированный язык Delphi. Варианты программного пакета. Особенности работы, вид экрана после запуска. Описание структуры программы.

    курсовая работа [1,3 M], добавлен 25.11.2014

  • Предмет объектно-ориентированного программирования и особенности его применения в средах Паскаль, Ада, С++ и Delphi. Интегрированная среда разработки Delphi: общее описание и назначение основных команд меню. Процедуры и функции программы Delphi.

    курсовая работа [40,8 K], добавлен 15.07.2009

  • Разработка программы проверки знаний для тестирования студентов по программированию с кодом на языке Delphi. Проектирование визуального интерфейса и словесный алгоритм работы программы. Алгоритмы разработанных процедур и функций, инструкция пользователя.

    курсовая работа [506,5 K], добавлен 21.02.2011

  • Анализ исходных данных. Определение структуры модуля для работы файлом. Разработка объектно-ориентированного приложения, использующего массив объектов, в среде Delphi. Модульная структура программного комплекса. Процедура сортировки методом вставки.

    курсовая работа [2,2 M], добавлен 20.09.2014

  • Организация работы в среде визуального программирования Delphi. Настройка, конфигурация и главное окно формы. Модификация формы, свойств и событий. Пиктографические кнопки, палитра компонентов, окно инспектора объектов. Процесс построения приложения.

    реферат [40,3 K], добавлен 23.01.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.