Шаг 308.
Создание внутрипроцессных серверов автоматизации. Создание и использование DLL. Вызов в DLL функций приложения (окончание)

    На этом шаге мы закончим изучение этого вопроса.

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

function GetNextValueExport:integer; stdcall;
begin
  if NSum<10 then begin
    Inc(NSum);
    Result := NSum;
  end else Result := -1;
end;

function CalculateSumExport(MethodName:PChar):Integer; stdcall;
  external 'FirstLib.dll' name 'SumExport';

procedure TForm1.Button1Click(Sender: TObject);
var
  N: Integer;
begin
  NSum := 0;
  N := CalculateSumExport('GetNextValueExport');
  Caption := IntToStr(N);
end;

exports {Эта секция объявлена в исполняемом файле}
  GetNextValueExport index 1 name 'GetNextValueExport';

    Обратите внимание - теперь в приложении (в проекте ЕХЕ-файла) определена секция exports! Соответствующий код в DLL для тестирования данной функции выглядит следующим образом:

type
  TReturnNextMethodExport=function:integer; stdcall;

function CalculateSumExport(MethodName:pchar):integer;
  stdcall; export;
var
  ReturnNextExport:TReturnNextMethodExport;
  N:integer;
begin
  Result := 0;
  N := 0;
  // Если параметр - нулевой, GetModuleHandle вернет
  // дескриптор файла, путем загрузки которого
  // создается вызывающий процесс.
  ReturnNextExport:=GetProcAddress(GetModuleHandle(NIL),
    MethodName);
  while N>=0 do begin
    N := ReturnNextExport;
    if N>=0 then Result:=Result+N;
  end;
end;
Текст этого приложения вместе с DLL можно взять здесь (414,8 Кб).

    При запуске этого проекта приложение автоматически загружает DLL и находит в DLL адрес функции CalculateNextExport (которая экспортируется по имени SumExport). При вызове этого проекта ему в качестве параметров передаются заголовок модуля приложения и имя функции, под которым она экспортируется из приложения. Далее, DLL использует функцию GetProcAddress для нахождения адреса функции, экспортируемой приложением. Для того чтобы был возвращен адрес функции, в приложении была объявлена секция exports, где описано внешнее имя функции. Этот пример иллюстрирует формально одинаковую структуру и способ формирования ЕХЕ- и DLL-файлов.

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

    На следующем шаге мы рассмотрим работу с объектами в DLL.




Предыдущий шаг Содержание Следующий шаг