Главная » Delphi » Обращение к функциям обратного вызова из библиотеки DLL

0

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

Листинг 6.10. Исходный код StrSrchLib.dll — обращение к функции об

ратного вызова из библиотеки  DLL

library StrSrchLib;

uses

Wintypes, WinProcs, SysUtils, Dialogs;

type

{ Объявление типа функции обратного вызова }

TFoundStrProc = procedure(StrPos: PChar); StdCall;

function SearchStr(ASrcStr, ASearchStr: PChar;

AProc: TFarProc): Integer; StdCall;

{ Эта функция выполняет поиск подстроки ASearchStr в строке

ASrcStr. В случае обнаружения искомой подстроки ASearchStr

вызывается процедура обратного вызова, заданная параметром Aproc

(если он был передан). Если в качестве значения этого параметра

пользователь передал значение nil, то эта процедура вызываться не

будет. }

var

FindStr: PChar;

begin

FindStr := ASrcStr;

FindStr := StrPos(FindStr, ASearchStr);

while FindStr <> nil do begin

if AProc <> nil thenTFoundStrProc(AProc)(FindStr); FindStr := FindStr + 1;

FindStr := StrPos(FindStr, ASearchStr);

end;

end;

exports

SearchStr;

begin

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

Собственно вызов  функции обратного вызова  осуществляется в экспортируемой процедуре SearchStr(). Работа  этой процедуры поясняется в комментариях.

Пример  использования этой   библиотеки  DLL  приведен  в  проекте  CallBack-

Demo.dpr. Исходный код главной формы этого  демонстрационного проекта можно

увидеть в листинге 6.11.

Листинг 6.11. Главная форма проекта DLL Callback

unit MainFrm;

interface uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

Forms, Dialogs, StdCtrls;

type

TMainForm = class(TForm)

btnCallDLLFunc: TButton;

edtSearchStr: TEdit;

lblSrchWrd: TLabel;

memStr: TMemo;

procedure btnCallDLLFuncClick(Sender: TObject);

end;

var

MainForm: TMainForm;

Count: Integer;

implementation

{$R *.DFM}

{ Определение экспортируемой процедуры библиотеки DLL }

function SearchStr(ASrcStr, ASearchStr: PChar;

AProc: TFarProc): Integer; StdCall external ‘STRSRCHLIB.DLL';

{ Определяя процедуру обратного вызова, не забудьте директиву

StdCall }

procedure StrPosProc(AStrPsn: PChar); StdCall;

begin

inc(Count); // Увеличить значение счетчика Count.

end;

procedure TMainForm.btnCallDLLFuncClick(Sender: TObject);

var

S: String;

S2: String;

begin

Count := 0; // Инициализировать счетчик Count нулевым значением

{ Длина текста, в котором осуществляется поиск подстроки. }

SetLength(S, memStr.GetTextLen);

{ Теперь скопировать этот текст в переменную S }

memStr.GetTextBuf(PChar(S), memStr.GetTextLen);

{ Скопировать текст Edit1 в строковую переменную, чтобы ее можно

было передать функции библиотеки DLL }

S2 := edtSearchStr.Text;

{ Вызов функции библиотеки DLL }

SearchStr(PChar(S), PChar(S2), @StrPosProc);

{ Вывод сведений о том, сколько раз заданное слово встречается в

строке. Результат содержится в счетчике Count, который

используется в функции обратного вызова }

ShowMessage(Format(‘%s %s %d %s’,

[edtSearchStr.Text, ‘occurs’, Count, ‘times.’]));

end;

end.В этом  приложении используется элемент управления класса  TMemo под  именем memStr. Свойство EdtSearchStr.Text компонента класса  TEdit содержит строку, которую  необходимо отыскать в содержимом компонента memStr. Содержимое объ екта memStr передается функции SearchStr() библиотеки DLL в качестве исходной строки, а значение свойства edtSearchStr.Text — в качестве искомой строки.

Функция  StrPosProc() —  это  используемая функция обратного вызова.  Она  уве личивает на единицу  значение глобальной переменной Count, предназначенной для хранения количества вхождений искомой строки в текст,  помещенный в компонент memStr.

Совместное  использование  DLL

несколькими процессами

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

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

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

Если планируется работа с 16 разрядным приложением, которое опирается на обще доступность глобальных данных  DLL, то можно  (как и прежде) предоставить такому приложению возможность совместного использования данных  DLL с другими  прило жениями. Этот процесс не является автоматическим, и для хранения общих данных  ис пользуются отображенные  в память  файлы, более  подробная информация о которых приведена в предыдущем издании Delphi 5 Руководство разработчика, в главе 12 — “Работа с файлами”. Здесь же воспользуемся ими лишь для иллюстрации данного метода.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии