delphi内存映射,跨平台

delphi内存映射(跨平台)

/// <author>cxg 2020-12-9</author>

unit yn.map;

interface

uses
  SysUtils,
  {$IFDEF posix}
  Posix.SysMman
  {$ENDIF}
  {$IFDEF mswindows}
  Windows
  {$ENDIF}
  ;

type
  PShareMem = ^TShareMem;

  TShareMem = record
    size: Cardinal;
    data: Pointer;
  end;

type
  TWriteRead = procedure (data: pointer) of object;

  TMemMap = class
  private
    FShareMemName: string;
    FFileHandle: THandle;
    p: PShareMem;
    FWrite: TWriteRead;
    FRead: TWriteRead;
  public
    constructor Create(const ShareMemName: string; data: Pointer; const dataLen: Cardinal); overload;
    destructor Destroy; override;
  public
    function createFileMap: Boolean;
    function map: Boolean;
    function unMap: Boolean;
    function openFileMap: Boolean;
    function closeFileMap: Boolean;
  public
    procedure write;
    procedure read;
  public
    property OnWrite: TWriteRead read FWrite write FWrite;
    property OnRead: TWriteRead read FRead write FRead;
  end;

implementation

{ TMemMap }

function TMemMap.closeFileMap: Boolean;
begin
  {$IFDEF mswindows}
  Result := CloseHandle(FFileHandle);
  {$ENDIF}
end;

constructor TMemMap.Create(const ShareMemName: string; data: Pointer; const dataLen: Cardinal);
begin
  FFileHandle := 0;
  FShareMemName := ShareMemName;
  New(p);
  p^.data := data;
  p^.size := dataLen;
end;

function TMemMap.createFileMap: Boolean;
begin
  {$IFDEF mswindows}
  FFileHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, p^.size, PChar(FShareMemName));
  Result := FFileHandle <> 0;
  {$ENDIF}
end;

destructor TMemMap.Destroy;
begin
  self.closeFileMap;
  Dispose(p^.data);
  Dispose(p);
  inherited;
end;

function TMemMap.map: Boolean;
begin
  {$IFDEF mswindows}
  p^.data := MapViewOfFile(FFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, p^.size);
  Result := p <> nil;
  {$ELSE}
  mmap(p^.data, p^.size, PROT_READ or PROT_WRITE, MAP_SHARED, 0, 0);
  {$ENDIF}
end;

function TMemMap.openFileMap: Boolean;
begin
  {$IFDEF mswindows}
  FFileHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, false, PChar(FShareMemName));
  Result := FFileHandle <> 0;
  {$ENDIF}
end;

procedure TMemMap.read;
begin
  openFileMap;
  self.map;
  if Assigned(FRead) then
    FRead(p^.data);
  Self.unMap;
end;

function TMemMap.unMap: Boolean;
begin
  {$IFDEF mswindows}
  Result := UnmapViewOfFile(p^.data);
  {$ELSE}
  munmap(p^.data, p^.size);
  {$ENDIF}
end;

procedure TMemMap.write;
begin
  if FFileHandle = 0 then
    self.createFileMap;
  map;
  if Assigned(FWrite) then
    FWrite(p^.data);
  Self.unMap;
end;

end.