Entwickler-Ecke

Free Pascal - Pointer auf MemorystreamInhalt


IhopeonlyReader - So 30.03.14 14:01
Titel: Pointer auf MemorystreamInhalt
Guten Tag,
ich möchte einen Stream versenden, da ich mit fpsend einen "Pointer" brauche, und weder @MyMemStream noch Pointer(MyMemStream) funktioniert, wüsste ich nicht wie ich es sonst machen soll..
aktuell lade ich den Stream in ein String und verschicke den String via fpsend mit @derString[1]

aber es gibt doch sicherlich einfacherer Methoden um einen Stream via fpsend zu versenden oder?
Wie kriege ich nun einen Pointer auf den Inhalt (z.B. erste Byte des MemoryStreams) ?

Ich möchte

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
 var PB: ^Byte;
MS: TMemoryStream;
Irgendwas: Integer;
begin
Irgendwas := $FF00AA55// -16733611, also in Bytes: 255,0,170,85
MS := TMemoryStream.create;
MS.Position := 0;
MS.Write( Irgendwas, 4 );
MS.Position := 0;
PB := Pointer(MS);
Showmessage( IntToStr(PB^) );// soll 255 stehen
inc(PB,1);
Showmessage( IntToStr(PB^) );//soll 0 stehen
inc(PB,1);
Showmessage( IntToStr(PB^) );//soll 170 stehen
inc(PB,1);
Showmessage( IntToStr(PB^) );//soll 85 stehen  
//freigeben und so :D


glotzer - So 30.03.14 15:16


Delphi-Quelltext
1:
MS.Memory                    


IhopeonlyReader - So 30.03.14 18:28

danke :)
allerdings ist hierbei zu beachten, dass GANZ am Anfang das zuletzt reingeschriebene steht !
Um also Byte für Byte (von vorne) zu lesen gilt

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var PB: ^Byte;
MS: TMemoryStream;
Irgendwas: Integer;
begin
Irgendwas := $FF00AA55// -16733611, also in Bytes: 255,0,170,85
MS := TMemoryStream.create;
MS.Position := 0;
MS.Write( Irgendwas, 4 );
MS.Position := 0;
PB := (MS.Memory);
inc( PB, MS.Size-1 );
Showmessage( IntToStr(PB^) );// hier steht nun 255 
dec(PB,1);
Showmessage( IntToStr(PB^) );//hier steht nun 0 
dec(PB,1);
Showmessage( IntToStr(PB^) );//hier steht nun 170 
dec(PB,1);
Showmessage( IntToStr(PB^) );//hier steht nun 85 
//freigeben und so :D


jfheins - So 30.03.14 20:29

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
danke :)
allerdings ist hierbei zu beachten, dass GANZ am Anfang das zuletzt reingeschriebene steht !
Um also Byte für Byte (von vorne) zu lesen gilt


Naja, das ist jetzt auch so wieder nicht richtig. Ein 32-Bit Integer liegt meistens* als little-Endian vor. (==> http://de.wikipedia.org/wiki/Little_endian )
Das niederwertigste Byte kommt also am Anfang. Das hat den Vorteil, dass ein Cast von Integer auf Byte die Adresse nicht ändert. Eine bestimmte Speicheradresse, an der der 32-bit Wert "200" steht, kannst du also auch als Byte lesen. Falls der Wert hinein passt, hast du direkt den richtigen Wert.

Solche Details versteckt der Compiler normalerweise, weil das für die meisten Fälle unwichtig ist. Falls du also mal auf die Idee kommst, deine Bytes einzeln hinein zu schreiben, dann werden die natürlich genau in der Reihenfolge dort stehen.


*= Das hängt von der CPU ab, x86 und AMD64 sind little-endian. ARM Prozessoren sind oft big-endian.


IhopeonlyReader - So 30.03.14 21:56

ich programmiere mit Lazarus sowohl auf einem x86 als auch einem ARM prozessor.. heißt das, dass es mit dem selben Code dort doch unterschiede geben kann?
und dort ein schwer zu findender Fehler sich verstecken könnte?


jfheins - So 30.03.14 23:24

Das würde ich zumindest erwarten. Genau genommen ist es aber egal auf welchem System du programmierst, viel wichtiger ist, für welchen Prozessor du programmierst :P


jaenicke - Mo 31.03.14 05:54

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
heißt das, dass es mit dem selben Code dort doch unterschiede geben kann?
und dort ein schwer zu findender Fehler sich verstecken könnte?
Hauptsächlich, wenn du es machst wie im Beispiel. Sprich einen Integerwert schreiben und einen Bytewert lesen.
Wenn du die gleiche Methode zum Lesen und Schreiben verwendest, ist es schon einmal sehr viel unwahrscheinlicher, dass ein Problem auftritt.

Was trotzdem passieren könnte, wäre der Unterschied Big Endian <> Little Endian. Ob das ein Problem ist, wenn du einen Stream auf x86 und ARM mit Lazarus benutzt und hin- und herschickst, kann ich dir nicht sagen, da unsere Cross Platform Lösungen dies bereits automatisch behandeln.
Das passiert so, dass es beim Senden in die Network Byte Order umgewandelt wird und beim Empfangen in die eigene Byteorder, falls notwendig. Dafür gibt es auch entsprechende Low-Level-Funktionen.