Avatar billede friiiiis Novice
09. april 2007 - 00:55 Der er 12 kommentarer og
1 løsning

MemoryMapped File - håndtere handle mellem 2 DLL eller DLL-EXE

Først: se dette spørgsmål placeret for LAAAANG tid siden:

http://www.eksperten.dk/spm/610268

Problemstilling:

Jeg vil overføre et handle fra en DLL fil (DLL fil 1) til en anden DLL fil (DLL fil 2) uden at lukke den DLL fil 1 ned.

Det svarer til at klikke "Apply" eller "Anvend" i windows og så udføres en funktion i DLL fil 2 uden at DLL fil 1 lukkes ned.

Borrisholt samt martinlind har løst problemet vha. memorymappedfile - se ovenstående spørgmål.

Mit spørgmål er nu: Kan nogen evt. sende mig noget delphikoden på hvordan man anvender memorymappedfile - eller endnu bedre - publicere det her på eksperten.dk - altså hvordan man benytter memorymappedfile...?

Jeg har nemlig ladet guldkornene fra martinlin og Borrisholt gå tabt, så jeg har ikke de vigtige kodelinier lige nu...
Avatar billede arne_v Ekspert
09. april 2007 - 02:27 #1
Jeg har følgende på lageret:

program shrmem;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

var
  mem : THandle;
  data : ^Integer;
  p : ^Integer;

begin
  mem := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 8192, 'GBLMEM');
  data := MapViewOfFile(mem, FILE_MAP_WRITE, 0, 0, 8192);
  data^ := 123;
  inc(data);
  data^ := 456;
  inc(data);
  data^ := 789;
  inc(data);
  UnmapViewOfFile(data);
  CloseHandle(mem);
end.
Avatar billede arne_v Ekspert
09. april 2007 - 02:28 #2
Det giver dig ihvertfald funktionerne der skal kaldes.

Den præcise brug afhænger af konteksten - der er mange muligheder.
Avatar billede borrisholt Novice
09. april 2007 - 15:08 #3
unit UnitGlobalData;

interface
uses
  Windows, Sysutils;
{$H-}

(*
The $H directive controls the meaning of the reserved word string when used alone in a type declaration.
The generic type string can represent either a long, dynamically-allocated string (the fundamental type AnsiString)
or a short, statically-allocated string (the fundamental type ShortString).

The {$H-} state is used here in order for getting a static size of our struct.
*)
type
  pInternalDATA = ^TInternalDATA;
  TInternalDATA = record
    DisplayString1, DisplayString2: string;
  end;

  TCustomSharedData = class
  private
    MapHandle: THandle;
    procedure FreeSharedData; virtual;
    procedure GetSharedData; virtual;
  protected
    InternalDATA: pInternalDATA;
  public
    constructor Create; virtual;
    destructor Destroy; override;
  end;

  TSharedData = class(TCustomSharedData)
  private
    function GetDisplayString1: string;
    procedure SetDisplayString1(const Value: string);
    function Getstring: string;
    procedure SetDisplayString2(const Value: string);
  public
    property DisplayString1: string read GetDisplayString1 write SetDisplayString1;
    property DisplayString2: string read Getstring write SetDisplayString2;
  end;

var
  SharedData: TSharedData = nil;
implementation

{ TCustomSharedData }

constructor TCustomSharedData.Create;
begin
  inherited;
  GetSharedData;
end;

destructor TCustomSharedData.Destroy;
begin
  FreeSharedData;
  inherited;
end;

procedure TCustomSharedData.GetSharedData;
var
  Size: integer;
begin
  { Get the size of the data to be mapped. }
  Size := SizeOf(TInternalDATA);

  { Now get a memory-mapped file object. Note the first parameter passes
    the value $FFFFFFFF or DWord(-1) so that space is allocated from the system's
    paging file. This requires that a name for the memory-mapped
    object get passed as the last parameter. }

  MapHandle := CreateFileMapping(DWORD(-1), nil, PAGE_READWRITE, 0, Size, '{45B05496-90D1-43C5-9142-97263A35A7EE}');

  if MapHandle = 0 then
    RaiseLastOSError;
  { Now map the data to the calling process's address space and get a
    pointer to the beginning of this address }
  InternalDATA := MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);

  if InternalDATA = nil then
  begin
    CloseHandle(MapHandle);
    RaiseLastOSError;
  end;
end;

procedure TCustomSharedData.FreeSharedData;
begin
  UnmapViewOfFile(InternalDATA);
  CloseHandle(MapHandle);
end;

{ TSharedData }

function TSharedData.Getstring: string;
begin
  Result := InternalDATA.DisplayString2;
end;

function TSharedData.GetDisplayString1: string;
begin
  Result := InternalDATA.DisplayString1;
end;

procedure TSharedData.SetDisplayString2(const Value: string);
begin
  InternalDATA.DisplayString2 := Value;
end;

procedure TSharedData.SetDisplayString1(const Value: string);
begin
  InternalDATA.DisplayString1 := Value;
end;

initialization
  if not IsLibrary then
    SharedData := TSharedData.Create;
finalization
  if not IsLibrary then
    FreeAndNil(SharedData);
end.
Avatar billede borrisholt Novice
09. april 2007 - 15:14 #4
Hej friiiiiiiiiiiis ;o)

Lidt forklaring. En memorymapped file er bare et stykke hukommelse som er shared mellem flere processer. To exe filler eller en exe filer og nogle DLL'er .. Altså globalt  i Windows shared data, ALLE der kender dit navn på din memorymapped file kan læse og skrive i den ... Navner er den sidste parameter i CreateFileMapping ... Lav derfor en unik streng ved i Delphi at trykke SHIFT + CTRL + G

Du laver dig en record med de datatyper du skal bruge, også en klasse der pakker den pænt ind. I det postede tilfælde deler jeg to strenge ...

Brugen af det er meget nemt, alle dine DLL'er og din Exe fil skal bare have uses UnitGlobalData (hvis din unit hedder det altså), og så kan du læse og skrive til den PRÆCIS som var det lokal hukommelse.

Håber det he bringer dig videre.

Jens B
Avatar billede borrisholt Novice
16. april 2007 - 08:20 #5
Fik du det til at virke ?
Avatar billede friiiiis Novice
16. april 2007 - 08:37 #6
Hej Borrisholt...

Som sædvanlig så har jeg har haft lidt travlt og her ikke haft tid til at kigge på det.

kan vi aftale at senest fredag vender jeg tilbage, så har jeg haft tid til at kigge på det... håber jeg, he, he...
Avatar billede borrisholt Novice
16. april 2007 - 11:32 #7
Det var nu ikke for at rykke for et svar, det var mere for at sikre mig at det ikke var en halv vind jeg lav løbet med.
Avatar billede friiiiis Novice
26. april 2007 - 19:09 #8
Hej,

lige et spørgmål så jeg kan komme videre...

Hvis jeg står i DLL fil 1 og skal udføre et eller andet i DLL fil 2 via "CreateFileMapping" (altså via det der stykke hukommelse) hvordan gør jeg så det?

ALtså hvordan kan Dll fil 2 "se" at jeg har ændret i "CreateFileMapping" hukommelsen?

Problemet i en nøddeskal er, at jeg kan kun finde ud af at sende data fra DLL fil 1 til DLL fil 2 ved at DLL fil 1 bliver lukket - jeg behøver "et eller andet" der tillader at man sender laver noget i dll fil 1, sender det over til dll fil 2 uden at dll fil 1 behøver at blive lukket...

hmmm.... sidder og tænker lidt over det her - det må være noget med den måde jeg kalder dll fil 1 på fra DLL fil 2....??
Avatar billede borrisholt Novice
01. maj 2007 - 12:18 #9
Hej

Der er desværre ingen måde hvor på du kan få et event fra WINDOWS OM AT DER ER SKREVET I EN MEMORY MAPPED FILE, MEN DU KAN BARE SCANNE DIN KLASSE HVERT SEKUND, OG SÅ AGERE I FORHOLD TIL DETTE. hVIS DU STADIG SIDDER helt FAST SÅ SKAL JEG LAVE ET EKSEMPEL TIL DIG. Hov nu fik jeg tænt for caps lock ;o)
Avatar billede friiiiis Novice
03. maj 2007 - 09:18 #10
Hej,

Du må  M E G E T gerne lave et eksempek til mig - bare ta' dig god tid - ingen hastværk - det er sådan set bare et eksempel på det der med at skanne min klasse jeg ikke kan finde ud af...
Avatar billede friiiiis Novice
17. maj 2007 - 12:11 #11
Hej Borrisholt,

du må meget gerne lave et eksempel til mig...

evt. henvis til et andet eksempel her på eksperten.dk hvor man laver det samme - altså det der med at "SCANNE DIN KLASSE HVERT SEKUND" ???
Avatar billede borrisholt Novice
18. maj 2007 - 14:30 #12
Nå ja undskyld dig kom jeg helt væk fra igen ....

Kyl mig en mail på jens@borrisholt.com, så skal jeg retunere et eksempel til dig.

Jens B
Avatar billede borrisholt Novice
06. juni 2007 - 09:00 #13
Hej Friiiiiiiis

Kom du nogensinde i luften med det projekt ?

Jens B
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester