メモリマップドファイル使用のサンプルソース


DLL1

DLL1は単純にユニット内でグローバル変数を宣言し、それをSetGRData()、 GetGRData()の2つのエクスポート関数によって、読み書きするためのDLLです。 本文にあるようにDLLを読込んだプロセス毎に prglobal1,unitglobal1の変数 領域が割り当てられます。
DLL1.dpr
library DLL1;

uses
  DLL1Main in 'DLL1Main.pas';

exports
  SetGRData,
  GetGRData;

{$R *.RES}

begin
end.

DLL1Main.pas
unit DLL1Main;

interface

var
  prglobal1:integer;

function SetGRData(V1,V2:integer):integer;export;stdcall;
function GetGRData(Value:integer):integer;export;stdcall;

implementation

var
  unitglobal1:integer;

function SetGRData(V1,V2:integer):integer;export;stdcall;
begin
  prglobal1 := V1;
  unitglobal1 := V2;
  result := 0;
end;

function GetGRData(Value:integer):integer;export;stdcall;
begin
  case Value Of
   1: result := prglobal1;
   2: result := unitglobal1;
  end;
end;
end.



DLL2 [ → DLL1.source ]

メモリマップドファイルを使って変数を共有できるようにしたものです。エクスポート関数などの型はDLL1と一緒です。
DLL2.dpr
library DLL2;

uses
  DLL2Main in 'DLL2Main.pas';

exports
  SetGRData,
  GetGRData;

{$R *.RES}

begin
end.

DLL2Main.pas
unit DLL2Main;

interface

uses
  Windows;

function SetGRData(V1,V2:integer):integer;export;stdcall;
function GetGRData(Value:integer):integer;export;stdcall;

implementation

type
  //共有データの構造体
  TShareData = record
    data1:integer;
    data2:integer;
  end;
  pShareData = ^TShareData;

const
  //MMFに割り当てるユニークな文字列
  uniqueString = 'This is Memory Mapped File Test!!!';
  

var
  hFMOBJ:THandle;

function SetGRData(V1,V2:integer):integer;export;stdcall;
var
  _hFMOBJ:THandle;
  p:pointer;
begin
  result := -1;

  //MMFをオープンする
  _hFMOBJ := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, uniqueString);
  if _hFMOBJ = 0 then begin
    exit;
  end;

  //MMFビューの割り当て
  p := pShareData(MapViewOfFile(_hFMOBJ, FILE_MAP_ALL_ACCESS, 0, 0, 0));
  if p = nil then begin
    Exit;
  end;

  //構造体にキャストしてデータにアクセス
  with pShareData(p)^ do begin
    data1 := V1;
    data2 := V2;
  end;

  //ビューの解除
  UnmapViewOfFile(p);
  //MMFを閉じる
  CloseHandle(_hFMOBJ);

  Result := hFMOBJ;
end;

function GetGRData(Value:integer):integer;export;stdcall;
var
  _hFMOBJ:THandle;
  p:pointer;
begin
  result := 0;

  //MMFオープン
  _hFMOBJ := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, uniqueString);
  if _hFMOBJ = 0 then begin
    Exit;
  end;

  //MMFビューの割り当て
  p := MapViewOfFile(_hFMOBJ, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  if p = nil then begin
    Exit;
  end;

  //構造体をキャストしてデータにアクセス
  with pShareData(p)^ do
    case Value Of
     1: result := Data1;
     2: result := Data2;
    end;

  //ビューの解除
  UnmapViewOfFile(p);
  //MMFを閉じる
  CloseHandle(_hFMOBJ);

end;

//MMF初期化(作成)
initialization
begin
  hFMOBJ := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE,
                                   0, SizeOf(TShareData), uniqueString);
end;

//MMFハンドル開放
finalization
begin
  if hFMOBJ = 0 then exit;
  CloseHandle(hFMOBJ);
end;

end.



DLL2-A

DLL2をすっきりさせたもの(MMFサンプルの最終形)。コードの見通しを良くするためにエラーに対してはほとんど考慮していません。上のDLL2Main.pasのコードに比べてすっきりしているのが分かると思います。実際に使う場合はGetFileMapObj(),ReleaseFileMapObj()でエラーハンドリングをするとか例外を発生させるなどして下さい。このサンプルではGetFileMapObj()でエラーが出るとマイナスを値を返すようにしています。呼び出し側では戻り値を使っていません。
DLL2AMain.pas
unit DLL2AMain;

interface

uses
  Windows;

type
  //共有データの構造体
  TShareData = record
    data1:integer;
    data2:integer;
  end;
  pShareData = ^TShareData;

function SetGRData(V1,V2:integer):integer;export;stdcall;
function GetGRData(Value:integer):integer;export;stdcall;

const
  //MMFに割り当てるユニークな文字列
  uniqueString = 'This is Memory Mapped File Test!!!';

var
  hFMOBJ:THandle;

implementation

//MMFオープン、MMFビューの設定
function GetFileMapObj(var h: THandle; var ptr: Pointer):integer;
begin
  //MMFをオープンする
  h := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, uniqueString);
  if h = 0 then begin
    result := -1;
    exit;
  end;

  //MMFビューの割り当て
  ptr := MapViewOfFile(_hFMOBJ, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  if ptr = nil then begin
    result := -2;
    Exit;
  end;
  
  result := 0;
end;

//MMFビューの解除、MMFハンドルのクローズ
function ReleaseFileMapObj(h: THandle; ptr: Pointer):integer;
begin
  //ビューの開放
  UnmapViewOfFile(ptr);
  //MMFを閉じる
  CloseHandle(h);

  result := 0;
end;

function SetGRData(V1,V2:integer):integer;export;stdcall;
var
  _hFMOBJ:THandle;
  p:pointer;
begin
  result := -1;
  
  GetFileMapObj(_hFMOBJ,p);
  
  //構造体にキャストしてデータにアクセス
  with pShareData(p)^ do begin
    data1 := V1;
    data2 := V2;
  end;

  ReleaseFileMapObj(_hFMOBJ, p);

  Result := hFMOBJ;
end;

function GetGRData(Value:integer):integer;export;stdcall;
var
  _hFMOBJ:THandle;
  p:pointer;
begin
  result := 0;
  
  GetFileMapObj(_hFMOBJ,p);
  
  //構造体をキャストしてデータにアクセス
  with pShareData(p)^ do
    case Value Of
     1: result := Data1;
     2: result := Data2;
    end;

  ReleaseFileMapObj(_hFMOBJ, p);

end;

//MMF初期化
initialization
begin
  hFMOBJ := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE,
                              0, SizeOf(TShareData), uniqueString);
end;

//MMFハンドル開放
finalization
begin
  if hFMOBJ = 0 then exit;
  CloseHandle(hFMOBJ);
end;

end.