[Delphi] Memory Mapped Files

Pagina: 1
Acties:
  • 305 views sinds 30-01-2008
  • Reageer

  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
Ik was bezig met memory mapped files. Ik heb een DLL gemaakt die een de Nu heb ik de volgende code:

code:
1
2
  MMF1handle, MMF2handle : cardinal;
  p1,p2 : ^string;


Dit staat onder de eerste knop en schrijft 'hallo' naar een memory mapped file.

code:
1
2
3
  MMFHandle1 := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf('hallo'), 'test');
  p1 := MapViewOfFile(MMFHandle1, FILE_MAP_WRITE,0,0,0);
  p1^ := 'hallo';


Om het er weer uit te lezen gebruik ik de volgende code:

code:
1
2
3
  MMFHandle2 := OpenFileMapping(PAGE_READWRITE, true, 'test');
  p2 := MapViewOfFile(MMFHandle2, FILE_MAP_READ,0,0,0);
  showmessage(p2^);


Op zich werkt het perfect binnen hetzelfde programma, alleen zodra ik het programma 2x opstart en probeer onderling data te versturen door MMF (door de ene de MMF aan te laten maken, en de andere deze MMF te laten openen), dan krijg ik die 'hallo' niet op mijn scherm (Ik krijg een '(' te zien, dus p2 point wel naar een waarde).

Ik heb ookal geprobeerd om alle MMF functies in een DLL te schrijven, alleen dan krijg ik binnen dezelfde applicatie ook gewoon de goede waarde. Ik kan alleen niet tussen verschillende applicaties data verzenden.

dus.. Iemand suggesties?

  • Korben
  • Registratie: Januari 2001
  • Laatst online: 14-11-2025

Korben

() => {};

Mjah, waarschijnlijk wordt je DLL niet geunload nadat je je applicatie afsluit, dat zou er mee te maken kunnen hebben. Sluit je al je handles wel af?

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
Ja ik sluit de Handles correct af. Maar al deed ik dit niet, dan zou het binnen dezelfde applicatie alsnog wel goed gaan. Maar waarom dan niet binnen verschillende applicaties

  • Korben
  • Registratie: Januari 2001
  • Laatst online: 14-11-2025

Korben

() => {};

mrClass schreef op 18 maart 2004 @ 15:51:
Ja ik sluit de Handles correct af. Maar al deed ik dit niet, dan zou het binnen dezelfde applicatie alsnog wel goed gaan. Maar waarom dan niet binnen verschillende applicaties
Hoe verzend je de data dan tussen verschillende applicaties? Gewoon variabelen opslaan en doorgeven werkt uiteraard niet.

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Je moet zeker geen gebruik maken van String object. Een String object is wat anders dan een char Pointer.

code:
1
 p1,p2 : ^string


Het is beter om

code:
1
 p1,p2 : PChar


te gebruiken omdat het gebruik van String 'gekke' resultaten geeft. Een String op zich is onderliggend als een (copy on write) pointer.

  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
Korben schreef op 18 maart 2004 @ 15:54:
[...]

Hoe verzend je de data dan tussen verschillende applicaties? Gewoon variabelen opslaan en doorgeven werkt uiteraard niet.
Dat is precies de reden waarom ik MMF gebruik, hiermee kan dat namelijk wel. Alleen krijg ik het niet aan de praat. Met MMF kun je door 2 applicaties hetzelfde deel van een File in het geheugen mappen. Op de bovenstaande manier dus (Zie TS). Hierdoor kun je naar de ene pointer schrijven (p1) en uit de ander(p2 die naar hetzelfde geheugen point) schrijven. Alleen ik doe iets fout.. maarwat..

  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
TijnFLiP schreef op 18 maart 2004 @ 15:59:
Je moet zeker geen gebruik maken van String object. Een String object is wat anders dan een char Pointer.

code:
1
 p1,p2 : ^string


Het is beter om

code:
1
 p1,p2 : PChar


te gebruiken omdat het gebruik van String 'gekke' resultaten geeft. Een String op zich is onderliggend als een (copy on write) pointer.
ooowk. Mooi dankje. rare windows met zijn Karakter pointers! |:( (Of rare delphi met zijn Strings). Ik dacht: ik gebruik gewoon een string pointer. Maar idd dat werkte niet nee. Maar nu wel :D thx _/-\o_

  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Een String is eigenlijk ook een pointer. Een String^ is dus eigenlijk een soort pointer naar een pointer. Een String in Delphi is een speciaal object omdat Delphi zorgt voor memory management zoals 'copy on demand', 'reference counting' etc. Gebruik Strings dus alleen zoals bedoeld en als je toch wil afwijken van de 'standaard' wees dan beducht voor memory management problemen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een PChar is toch eigenlijk ook gewoon een pointer naar een char? Waarom gaat de assignment in dat geval dan wel goed? Of kopieert delphi dan de hele array?

Ik krijg namelijk het vermoeden dat het "bij toeval" goed gaat. Een string wordt ergens in de executable opgenomen, en heeft vrijwel altijd hetzelfde adres als je je applicatie opstart. Als jij dus die pointerwaarde naar de MMF schrijft, en je leest dat in een nieuwe instance van je applicatie weer in, dan staat er op dat adres natuurlijk ook gewoon nog steeds die string. Als je de 2e keer een andere applicatie opstart die die MMF inleest gaat het denk ik gewoon keihard fout (omdat die 2e applicatie niet die string op dat adres heeft staan)

[ Voor 64% gewijzigd door .oisyn op 18-03-2004 16:21 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
Mijn verklaring is de volgende:

Omdat een String^ eigenlijk een pointer naar een pointer is zal de code

p1^ := 'hallo'

dus ervoor zorgen dat in MMF een pointer staat naar die String ('hallo' is geconverteerd naar een string). Dit werkt wel binnen dezelfde applicatie omdat die String dan bereikbaar is. Het gaat echter mis tussen applicaties omdat een pointer niet uitwisselbaar is.

.oisyn heeft gelijk. Was nog vergeten te melden dat je wel Move moet gebruiken om de MMF te vullen met de string omdat het zoals hij aangeeft dan ook nog mis gaat.

[ Voor 21% gewijzigd door martijn_brinkers op 18-03-2004 16:27 ]


  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
.oisyn schreef op 18 maart 2004 @ 16:18:
Een PChar is toch eigenlijk ook gewoon een pointer naar een char? Waarom gaat de assignment in dat geval dan wel goed? Of kopieert delphi dan de hele array?

Ik krijg namelijk het vermoeden dat het "bij toeval" goed gaat. Een string wordt ergens in de executable opgenomen, en heeft vrijwel altijd hetzelfde adres als je je applicatie opstart. Als jij dus die pointerwaarde naar de MMF schrijft, en je leest dat in een nieuwe instance van je applicatie weer in, dan staat er op dat adres natuurlijk ook gewoon nog steeds die string. Als je de 2e keer een andere applicatie opstart die die MMF inleest gaat het denk ik gewoon keihard fout (omdat die 2e applicatie niet die string op dat adres heeft staan)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure Write(p : pchar; value : string);
var
  i : integer;
begin
  for i := 1 to length(value) do
  begin
    (p+i)^ := value[i];
  end;
  (p+i+1)^ := #0;
end;

function Read(p : pchar) : string;
begin
  result := string(p+1);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  stri : array[0..200] of char;
begin
  MMFHandle1 := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0, sizeof('hallo'), 'klaas');
  p1 := MapViewOfFile(MMFHandle1, FILE_MAP_WRITE,0,0,0);
  write(p1,'klaas');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  MMFHandle2 := OpenFileMapping(PAGE_READWRITE, false, 'klaas');
  p2 := MapViewOfFile(MMFHandle2, FILE_MAP_READ,0,0,0);
  showmessage(read(p2));
end;


zoals je ziet heb ik het nu met en Pchar gedaan en werkt het goed. Ik zit alleen met bepaalde vragen, waarom dit werkt.
Ik heb de procedure Read en Write gemaakt, om het toch als een string type te kunnen behandelen.
Wat ik me dus afvraag is: hoe kan ik van en string een pchar maken (Zonde mijn Read en Write methodes)? Niet op de volgende manier:
code:
1
2
3
p : pchar;
s : string;
p := pchar(s);

Want in dit geval schrijf je de pointer over.
Maar dit kan ook niet:
code:
1
2
3
p : pchar;
s : string
p^ := pchar(s);

Dit kan ook niet omdat p^ gewoon een char is en geen pchar.

Wat is niet aan mijn read snap, is waarom string(p+1) wel werkt en gewoon string(p) niet?!

  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 31-10-2025
komt omdat je

(p+i)^ := value[i]; en

(p+i+1)^ := #0; gebruikt maar moet denk ik zijn


(p+i-1)^ := value[i]; en

(p+i)^ := #0;

Dit omdat je I bij 1 laat beginnen. Je kan het geheel ook met een Move doen. Zoiets als (niet getest!!)

Move( SomeString, p1^, Length( SomeString) )

[ Voor 15% gewijzigd door martijn_brinkers op 18-03-2004 16:34 ]


  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
TijnFLiP schreef op 18 maart 2004 @ 16:33:
komt omdat je

(p+i)^ := value[i]; en

(p+i+1)^ := #0; gebruikt maar moet denk ik zijn


(p+i-1)^ := value[i]; en

(p+i)^ := #0;

Dit omdat je I bij 1 laat beginnen. Je kan het geheel ook met een Move doen. Zoiets als (niet getest!!)

Move( SomeString, p1^, Length( SomeString) )
Stom |:( inderdaad, je hebt gelijk(Het eerste gedeelte)
En inderdaad dat move werkt ook goed. koel. Nu is hij perfect. :7

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Een PChar is toch eigenlijk ook gewoon een pointer naar een char? Waarom gaat de assignment in dat geval dan wel goed? Of kopieert delphi dan de hele array?
Delphi reserveert ruimte voor 2 integers direct vóór de eigenlijke string, hier wordt de referentieteller en stringlengte opgeslagen.
In de code uit de eerste post gaat Delphi er van uit dat deze gegevens aanwezig zijn.

Developer Accused Of Unreadable Code Refuses To Comment


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nu heb je het gewoon over het native string type, niet over PChar
(oh, misschien bedoelde je alleen maar uit te leggen waarom het in het eerste geval juist fout gaat, dat snap ik idd, het ging mij meer om waarom het bij PChar goed ging ;))

[ Voor 58% gewijzigd door .oisyn op 18-03-2004 17:14 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
.oisyn schreef op 18 maart 2004 @ 17:13:
Nu heb je het gewoon over het native string type, niet over PChar
(oh, misschien bedoelde je alleen maar uit te leggen waarom het in het eerste geval juist fout gaat, dat snap ik idd, het ging mij meer om waarom het bij PChar goed ging ;))
Omdat de pointer in het geheugen, op een bepaalde plaats een karakter aanwijst. Dus als je inderdaad p^ opvraagt krijg gewoon een char. Maar je kan het zien, dat een PChar een reeks karakters (String) aanwijst. Dus dan kun je ook doen (p+1)^ voor het tweede karakter van de string. Maar net hoeveel geheugen er voor deze #0 terminated string nodig is.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 15:56

Tomatoman

Fulltime prutser

Het native datatype string is reference counted. Zodra je vanuit twee applicaties dezelfde string gebruikt, gaat het reference counting mechanisme de mist in. Maar er is weing mis mee om gewoon PChars te gebruiken, die niet reference counted zijn. Conversie van string naar PChar doe je gewoon door de string te typecasten als PChar:
Delphi:
1
2
3
4
5
var
  S: string;
  PCh: PChar;
begin
  PCh := PChar(S);
De andere kant op is nog gemakkelijker:
Delphi:
6
  S := PCh;
Zolang je in de memory mapped file alleen PChars gebruikt, gaat alles goed.

Een goede grap mag vrienden kosten.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

mrClass schreef op 19 maart 2004 @ 10:07:
[...]


Omdat de pointer in het geheugen, op een bepaalde plaats een karakter aanwijst. Dus als je inderdaad p^ opvraagt krijg gewoon een char. Maar je kan het zien, dat een PChar een reeks karakters (String) aanwijst. Dus dan kun je ook doen (p+1)^ voor het tweede karakter van de string. Maar net hoeveel geheugen er voor deze #0 terminated string nodig is.
uh ja, je hoeft mij niet uit te leggen hoe pointers werken hoor ;) Zie ook [rml].oisyn in "[ Delphi] Memory Mapped Files"[/rml]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
.oisyn schreef op 19 maart 2004 @ 14:18:
[...]


uh ja, je hoeft mij niet uit te leggen hoe pointers werken hoor ;) Zie ook [rml].oisyn in "[ Delphi] Memory Mapped Files"[/rml]
offtopic:
Xcuses, maar ja misschien is het voor andere mensen die het lezen ook leerzaam. ;)

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 26-05 11:18

alienfruit

the alien you never expected

Pagina: 1