Delphi: обмен данными между приложениями

Delphi: обмен данными между приложениями

Не менее мощным и гибким методом организации обмена данными между приложениями является метод, который базируется на проецируемых в память файлах (Files Mapping). Главная идея этого механизма основывается на использовании динамической разделяемой памяти системы для хранения в ней данных. Как известно, каждый процесс имеет свой участок памяти, называемый виртуальным адресным пространством. При использовании механизма проецируемых в память файлов данные становятся доступны из любого процесса, который использует этот файл. В этом случае говорят, что файл отображается в виртуальное адресное пространство процесса, поэтому данные, хранимые в файле, доступны процессу, который этот файл открыл. Механизм проецирования файлов в память используется, например, для исполняемых файлов приложений, а также для DLL.

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

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

  • hFile - должен содержать дескриптор открытого файла, для которого будет создаваться объект, отображающий этот файл в память процесса.
  • lpFileMappingAttributes - указатель на структуру TSecurityAttributes. Если указателю присвоить nil, то атрибуты защиты устанавливаются по умолчанию.
  • flProtect - содержит флаги, которые задают режимы доступа к виду файла в памяти процесса. Этот параметр может принимать одно из следующих значений:
    • PAGE_READONLY — из вида файла можно только читать данные;
    • PAGE_READWRITE — разрешает чтение и запись данных в вид файла;
    • PAGE_WRITECOPY — разрешает чтение и запись данных в вид файла, но при записи создается новая копия вида файла.

    В случае успешного завершения эта функция возвращает дескриптор объекта (THandle), отображающего файл в память, а в случае неудачи — 0.

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

    • hFileMappingObject - должен содержать дескриптор объекта, отображающего файл в память, который был предварительно создан функцией CreateFileMapping.
    • dwDesiredAccess - задает режим доступа к виду файла и может принимать одно из следующих значений:
      • FILE_MAP_WRITE - чтение и запись в вид файла;
      • FILE_MAP_READ — только чтение из вида файла;
      • FILE_MAP_ALL_ACCESS — чтение и запись в вид файла;
      • FILE_MAP_COPY — при записи в вид файла создается его копия, а исходный файл не изменяется.

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

      Следующей функцией, противоположной по производимым действиям функции MapViewOfFile, является UnMapViewOfFile. Она отключает проецируемый файл от текущего процесса:

      Функция принимает указатель, возвращаемый MapViewOfFile, и использует его для отмены проекции файла на адресное пространство процесса. В случае успешной выгрузки функция возвращает True, в противном случае — False.

      И последняя функция, которую необходимо рассмотреть, — это CloseHandle. Она используется для закрытия дескриптора (многих системных объектов, а не только проекции файла).

      Как видно из синтаксиса функции, она принимает описатель объекта файлового отображения, полученный в результате выполнения функции CreateFileMapping и освобождает его. Для правильного завершения работы с объектом файлового отображения сначала следует применить функцию UnMapViewOfFile, а затем CloseHandle.

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

      Для демонстрации работы проецируемых в память файлов создадим приложение, которое будет записывать в такой файл строку и спустя некоторое время считывать ее оттуда. Для этого нам понадобится стандартный TextBox, кнопка, метка и таймер. Программа будет работать следующим образом: строка, записанная в поле редактора, после нажатия кнопки помещается в проецируемый файл. Далее, спустя некоторое время (задается таймером = 1 сек.), содержимое файла считывается и задается в качестве заголовка метки.

      В секцию описания переменных программы помещаем следующие объявления:

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

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

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

      Используемая литература: Программирование в Delphi. Трюки и эффекты. Александр Чиртик