浅谈Delphi中进程间的数据共享


  DLL是 缔造Windows 利用程序,实现代码重用的主要 目的 。那么当我们需求在 历程间共享数据时, 怎么做 威力快捷容易地实现呢?在32位 利用系统中,每个 利用程序会将DLL映射到自己的地址空间,同时DLL中的数据也就随之被映射了 。这样,每个 利用程序都有自己的数据实例,在一个 利用程序中 批改DLL中的全局变量,不会影响其它的 利用程序 。DLL的 使用 仿佛与我们的 目标相背离,那么如何 威力实现我们想要的东东呢?这里给大家介绍一种特别的技术,那便是内存映射文件 。

  内存映射文件提供了一种 步骤,便是在WIN32系统的地址空间保留一块内存区域,物理存储 可以向其中提交 。而且内存映射文件 不仅是磁盘文件,也 可以是WIN32的页面文件,而且后者比前者要好,由于这 象征着 可以像 拜访一个磁盘文件那样 拜访内存中的一个区域,而不用 缔造暂时文件,用完后还得删除它 。WIN32有自己的治理页面调度文件,当不需求页面调度文件时,系统会自动将有关区域 开释 。以下是具体的实现代码:

library Project1;

uses

shareMem,

windows,

SysUtils,

Classes;

const

 MFileName: Pchar = ’ShareData’;

 //定义一个记录类型,你所需求共享的数据就 保留在这里 。

 //当在 历程中调用GetDllData时, 历程中也应该定义一个与这个一样的记录类型 。

type

 PGlobalDllData = ^TGlobalDllData;

 TGlobalDllData = record

 s: string[50];

 i: integer;

end;

var

 GlobalData: PGlobalDllData; //这是一个全局变量,指向 缔造的内存映射文件 。

 MapHandle: THandle;

 //给外部 历程调用的过程,当外部 历程调用这个过程后,形参AGlobalData就指向了我//们 缔造的内存映射文件. 我们 可以 缔造两个 历程, 同时调用这个过程, 那么在其中一个进 //程中 批改数据后, 在另外一个 历程中既可 反响出来, 实现了我们需求的共享.

procedure GetDllData(var AGlobalData: PGlobalDllData);stdcall; begin

 AGlobalData := GlobalData;

end;

procedure OpenThisData;

var

 size: integer;

begin

 size := sizeof(TGlobalDllData);

 // 缔造一个内存文件映射对象,MfileName 保留的值便是该对象的名字 。

 mapHandle := CreateFileMapping(Dword(-1), nil, page_readWrite, 0, size, MFileName);

 if mapHandle = 0 then

  RaiseLastWin32Error;

  //把文件的视图映射到调用 历程的地址空间,该函数的返回值便是该对象的首地址 。注//意,这是调用 历程的地址,两个 利用程序调用该DLL,返回值是不一样的 。

 GlobalData := MapViewOfFile(mapHandle, File_map_all_Access, 0, 0, size);

 Globaldata^.s := ’TEST’;

 GlobalData^.i := 5;

 if GlobalData = nil then

 begin

  CloseHandle(MapHandle);

  RaiseLastWin32Error;

 end;

end;

//DLL从 历程中 拆散出来时,应该 开释相应的空间

procedure CloseThisData;

begin

 unmapViewOfFile(GlobalData);

 closeHandle(MapHandle);

end;

procedure DllEntryPoint(dwReason: DWord);

begin

 case dwReason of

  Dll_Process_Attach: OpenThisData; //调用DLL时传入的参数,由系统自动传入

  Dll_Process_Detach: CloseThisData; // 开释DLL时传入的参数,系统自动传入 。

 end;

end;

{$R *.res}

exports

 GetDllData; //外部 利用程序调用的便是这个过程 。

 

begin

 DllProc := @DllEntryPoint; //该变量是一个全局变量,由它来指定DLL的入口及出 //口函数 。

 DllEntryPoint(Dll_Process_Attach);

end.

//以上代码在DELPHI6中编译通过 。