違うプログラムでオブジェクトのメモリ共有をするには?

解決


cocomo  2008-06-05 20:49:35  No: 30911

Delphi7 WindowsXP です。

CreateFileMappingを使って文字列やarrayなどは共有できるのですが、
TStringList の AddObject を使ったオブジェクトが取得できません。
同一プログラム内でMapViewOfFileを使うと取得できるのですが、
プログラムを二つ立ち上げて共有させようとすると何も取得できません。
CreateFileMappingでは出来ないのでしょうか?何か他の方法があるので
しょうか?サンプルを書いてみました。よろしくお願いします。

type
  TData = class(TObject)
  public
    FData1 : String;
    FData2 : String;
  end;

  TForm1 = class(TForm)
    (略)
  private
    wStringList1 : TStringList;
  public
  end;

var
  Form1: TForm1;
  HFILE: THandle; // マッピングファイルオブジェクトのハンドル

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  wStringList1 := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  idx : Integer;
begin
  for idx := wStringList1.Count -1 downto 0 do
    wStringList1.Objects[idx].Free;
  wStringList1.Free;
  CloseHandle( HFILE );
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  wData : TData;
  idx   : Integer;
begin
  for idx := 0 to 10 do
  begin
    wData := TData.Create;
    wData.FData1 := Format('%8.8d',[idx]);
    wData.FData2 := Format('%8.8d',[idx*10]);
    wStringList1.AddObject(wData.FData1,wData);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  idx : Integer;
begin
  for idx := 0 to wStringList1.Count-1 do
    with TData(wStringList1.Objects[idx]) do
      ListBox1.Items.Add(FData1+'|'+FData2);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  P1 : Pointer;
begin
  HFILE := CreateFileMapping( $FFFFFFFF, nil, PAGE_READWRITE,
                     0, SizeOf(wStringList1), '_FileMappingTest' );

  if HFILE <> 0 then
  begin
    P1 := MapViewOfFile( HFILE, FILE_MAP_WRITE, 0, 0, 0 );
    if P1 <> nil then
    begin
      CopyMemory( P1, @wStringList1, SizeOf(wStringList1) );
      UnmapViewOfFile( P1 );
    end;
  end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  HF  : THandle;
  P2  : Pointer;
  ST  : TStringList;
  idx : Integer;
begin
  HF := OpenFileMapping( FILE_MAP_READ, False, '_FileMappingTest' );
  if HF <> 0 then
  begin
    P2 := MapViewOfFile( HF, FILE_MAP_READ, 0, 0, 0 );
    if P2 <> nil then
    begin
      CopyMemory( @ST, P2, SizeOf( ST )); //ClassはTStringListに
      UnmapViewOfFile( P2 );              //なってくれている
      for idx := 0 to ST.Count -1 do      //ST.Count が 0 になる
      begin
        with TData(ST.Objects[idx]) do
        begin
          ListBox2.Items.Add(FData1 + '|' + FData2);
        end;
      end;
    end;
  end;
end;


通りすがり  2008-06-05 20:56:38  No: 30912

オブジェクト参照はポインタです。共有メモリを使って正しく参照を渡せたとしても、
それを使うことはできません。オブジェクトの本体を渡せないのですから。


cocomo  2008-06-06 02:56:14  No: 30913

通りすがりさんありがとうございます。
やはりオブジェクトの本体は渡せないですよね。
DBのマスター系をメモリに持ってプログラムごとDB参照するのを
止めようかと思って考えてました。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加