Sharing data array between two applications in Delphi

前端 未结 2 613
Happy的楠姐
Happy的楠姐 2020-12-09 19:41

I want to share array data between two applications. In my mind, first program create the array and the second program can read the array from already allocated memory area.

2条回答
  •  春和景丽
    2020-12-09 20:33

    Scratched my head thinking of what a short-but-complete example of sharing memory between two applications might be. The only option is a console application, GUI applications require a minimum of 3 files (DPR + PAS + DFM). So I cooked up a small example where one integers array is shared using a memory mapped file (backed by the page file so I don't need to have a phisical file on disk for this to work). The console application responds to 3 commands:

    • EXIT
    • SET NUM VALUE Changes the value at index NUM in the array to VALUE
    • DUMP NUM displays the value in the array at index NUM
    • DUMP ALL displays the whole array

    Of course, the command processing code takes up about 80% of the whole application. To test this compile the following console application, find the executable and start it twice. Go to the first window and enter:

    SET 1 100
    SET 2 50
    

    Go to the second console and enter this:

    DUMP 1
    DUMP 2
    DUMP 3
    SET 1 150
    

    Go to the first console and enter this:

    DUMP 1
    

    There you have it, you've just witnessed sharing memory between two applications.

    program Project2;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils, Windows, Classes;
    
    type
      TSharedArray = array[0..10] of Integer;
      PSharedArray = ^TSharedArray;
    
    var
      hFileMapping: THandle; // Mapping handle obtained using CreateFileMapping
      SharedArray: PSharedArray; // Pointer to the shared array
      cmd, s: string;
      num, value, i: Integer;
      L_CMD: TStringList;
    
    function ReadNextCommand: string;
    begin
      WriteLn('Please enter command (one of EXIT, SET NUM VALUE, DUMP NUM, DUMP ALL)');
      WriteLn;
      ReadLn(Result);
    end;
    
    begin
      try
        hFileMapping := CreateFileMapping(0, nil, PAGE_READWRITE, 0, SizeOf(TSharedArray), '{C616DDE6-23E2-425C-B871-9E0DA54D96DF}');
        if hFileMapping = 0 then
          RaiseLastOSError
        else
          try
            SharedArray := MapViewOfFile(hFileMapping, FILE_MAP_READ or FILE_MAP_WRITE, 0, 0, SizeOf(TSharedArray));
            if SharedArray = nil then
              RaiseLastOSError
            else
              try
                WriteLn('Connected to the shared view of the file.');
    
                cmd := ReadNextCommand;
                while UpperCase(cmd) <> 'EXIT' do
                begin
                  L_CMD := TStringList.Create;
                  try
                    L_CMD.DelimitedText := cmd;
                    for i:=0 to L_CMD.Count-1 do
                      L_CMD[i] := UpperCase(L_CMD[i]);
    
                    if (L_CMD.Count = 2) and (L_CMD[0] = 'DUMP') and TryStrToInt(L_CMD[1], num) then
                      WriteLn('SharedArray[', num, ']=', SharedArray^[num])
                    else if (L_CMD.Count = 2) and (L_CMD[0] = 'DUMP') and (L_CMD[1] = 'ALL') then
                      begin
                        for i:= Low(SharedArray^) to High(SharedArray^) do
                          WriteLn('SharedArray[', i, ']=', SharedArray^[i]);
                      end
                    else if (L_CMD.Count = 3) and (L_CMD[0] = 'SET') and TryStrToInt(L_CMD[1], num) and TryStrToInt(L_CMD[2], value) then
                      begin
                        SharedArray^[num] := Value;
                        WriteLn('SharedArray[', num, ']=', SharedArray^[num]);
                      end
                    else
                       WriteLn('Error processing command: ' + cmd);
    
                  finally L_CMD.Free;
                  end;
    
                  // Requst next command
                  cmd := ReadNextCommand;
                end;
    
    
              finally UnmapViewOfFile(SharedArray);
              end;
          finally CloseHandle(hFileMapping);
          end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
    

提交回复
热议问题