TMemoryStream Pointer

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 6162
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

TMemoryStream Pointer

Beitrag von Mathias »

Wieso bekomme ich hier folgende Fehlermeldung ?

Code: Alles auswählen

unit1.pas(60,14) Error: Illegal type conversion: "TMesswert" to "Pointer"


Unter Linux 64Bit ohne Probleme, aber Win32 macht den Fehler.
Wie kann ich das Plattform übergreifend machen ?

Code: Alles auswählen

type
  TMesswert = record
    ma, mm: single;
  end;
 
var
  ms: TMemoryStream;
  mw: TMesswert;
begin
  ms := TMemoryStream.Create;
  ms.Write(Pointer(mw), SizeOf(TMesswert)); // Fehler
  ms.Free;
end
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TMemoryStream Pointer

Beitrag von wp_xyz »

Wieso konvertierst du da den Record zu einem Pointer? Die Write-Methode eines Streams hat den 1. Parameter doch als untypisiertes var, d.h. du kannst jede Variable direkt hinschreiben (wir sind hier bei Pascal, nicht bei C):

Code: Alles auswählen

  ms.Write(mw, SizeOf(TMesswert)); 

Mathias
Beiträge: 6162
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TMemoryStream Pointer

Beitrag von Mathias »

Danke, habe anscheinend viel zu weit gesucht.
Aber wieso hat er unter Linux nicht gemotzt ?

(wir sind hier bei Pascal, nicht bei C):

Das kommt bei mir von OpenGL, da muss man den Puffer mit Pointer(x) übergeben.

Ich habe nochmals nachgeguckt, der kleine Unterschied macht es aus.

Code: Alles auswählen

procedure xxx(const data: Pointer)  // OpenGL
procedure xxx(const data)  // MemoryStream


Bei einer dynamischen Array sieht es auch ein bisschen anders aus.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TMemoryStream Pointer

Beitrag von wp_xyz »

Mathias hat geschrieben:Bei einer dynamischen Array sieht es auch ein bisschen anders aus.

Da nehme ich immer das Element mit Index 0:

Code: Alles auswählen

type
  TDataElement = record
    x, y: Double;
  end;
var
  data: array of TDataElement;
begin
  SetLength(data, 100);
  FuelleArrayMitDaten(data);
  Stream.Write(data[0], Length(data) * SizeOf(TDataElement));

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TMemoryStream Pointer

Beitrag von Socke »

Mathias hat geschrieben:Danke, habe anscheinend viel zu weit gesucht.
Aber wieso hat er unter Linux nicht gemotzt ?

Code: Alles auswählen

type
  TMesswert = record
    ma, mm: single;
  end;
// allgemein
sizeof(single) = 4 byte
sizeof(TMesswert) = 8 byte // Annahme, siehe Dokumentation zu packed records
// linux 64bit
sizeof(Pointer) = 8 byte = sizeof(TMesswert)
// windows 32 bit
sizeof(Pointer) = 4 byte <> sizeof(TMesswert)

Es liegt nicht am Betriebssystem sondern an der Prozessorarchitektur.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: TMemoryStream Pointer

Beitrag von marcov »

Mathias hat geschrieben:Ich habe nochmals nachgeguckt, der kleine Unterschied macht es aus.

Code: Alles auswählen

procedure xxx(const data: Pointer)  // OpenGL
 



Mann muss ein Pointer geben.

Code: Alles auswählen

 
procedure xxx(const data)  // MemoryStream

[/code]


Was man an xxx mitgibt, wird von FPC automatisch nach ein Zeiger konvertiert.

Also

Code: Alles auswählen

 
  irgendeinerstream.Write(mw,sizeof(mw))
[/quote]
 
gibt ein pointer nach "mw" an "write".
 
Wenn mann
 
[code=laz]
  irgendeinerstream.Write(@mw,sizeof(mw))
 


oder so schreibt, also pointer nach mw, dan wird nimmt FPC ein Pointer nach den Platz wo der pointer nach mw gespeichert ist!

Mathias
Beiträge: 6162
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TMemoryStream Pointer

Beitrag von Mathias »

wp_xyz hat geschrieben:
Mathias hat geschrieben:Bei einer dynamischen Array sieht es auch ein bisschen anders aus.

Da nehme ich immer das Element mit Index 0:

Code: Alles auswählen

type
  TDataElement = record
    x, y: Double;
  end;
var
  data: array of TDataElement;
begin
  SetLength(data, 100);
  FuelleArrayMitDaten(data);
  Stream.Write(data[0], Length(data) * SizeOf(TDataElement));

Dies ist ein gefährlicher Weg, wen Length(data) = 0 ist.

Code: Alles auswählen

Stream.Write(Pointer(data), Length(data) * SizeOf(TDataElement));

Oder funktioniert dies auch nur mit 64 Bit ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TMemoryStream Pointer

Beitrag von wp_xyz »

Mathias hat geschrieben:
wp_xyz hat geschrieben:
Mathias hat geschrieben:Dies ist ein gefährlicher Weg, wen Length(data) = 0 ist.

Je nachdem... In der Standardeinstellung, wenn Range-Check aus ist, merkt man davon gar nichts, weil bei Length(data)=0 gar nichts geschrieben, das Array-Element[0] also gar nicht angesprochen wird.

Wenn natürlich Range-Checking an ist, gibt es einen Laufzeitfehler 201. Daher - du hast recht - ist es natürlich sauberer, die Länge zu prüfen:

Code: Alles auswählen

 if Length(data) > 0 then Stream.Write(data[0], Length(data) * SizeOf(TDataElement));

Mathias
Beiträge: 6162
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TMemoryStream Pointer

Beitrag von Mathias »

Wen ich dich richtig verstehe, ist es besser auf Length=0 zu prüfen, anstelle von Pointer zu verwenden ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TMemoryStream Pointer

Beitrag von wp_xyz »

Mathias hat geschrieben:Wen ich dich richtig verstehe, ist es besser auf Length=0 zu prüfen, anstelle von Pointer zu verwenden ?

Was meinst du mit "Pointer verwenden"?

Mathias
Beiträge: 6162
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TMemoryStream Pointer

Beitrag von Mathias »

Was meinst du mit "Pointer verwenden"?

Ich hatte mal einen Versuch mit TFileStream gemacht, dort hatte ich auch mit Pointer gearbeitet.
Aber ich sehe gerade, das ich hinter Pointer noch ein ^ gesetzt habe.

Code: Alles auswählen

var
  fs: TFileStream;
  //  s: string;
  s: array of char;
 
  procedure Ausgabe(s: array of char);
  var
    i: integer;
  begin
    WriteLn(Length(s));
    for i := 0 to Length(s) - 1 do begin
      Write(s[i]);
    end;
    WriteLn();
    for i := 0 to Length(s) - 1 do begin
      Write(byte(s[i]), ' ');
    end;
    WriteLn();
  end;
 
begin
  fs := TFileStream.Create('Test.txt', fmCreate);
  try
    s := 'Test';
    Ausgabe(s);
    fs.Write(Pointer(s)^, Length(s));
    fs.Write(PChar(s)^, Length(s));
    fs.Write(s[0], Length(s));
    s := '';
    fs.Write(Pointer(s)^, Length(s));
    fs.Write(PChar(s)^, Length(s));
    fs.Write(s[0], Length(s))// Hier knallt es
    s := 'Letzt Zeile';
    fs.Write(Pointer(s)^, Length(s));
  finally
    fs.Free;
  end;
 
  fs := TFileStream.Create('Test.txt', fmOpenRead);
  try
    s := '    ';
    fs.Read(Pointer(s)^, Length(s));
    Ausgabe(s);
    fs.Read(PChar(s)^, Length(s));
    Ausgabe(s);
    fs.Read(s[0], Length(s));
    WriteLn(PChar(s));
    s := '';
    fs.Read(Pointer(s)^, Length(s));
    Ausgabe(s);
    fs.Read(PChar(s)^, Length(s));
    Ausgabe(s);
    s := '            ';
    fs.Read(Pointer(s)^, Length(s));
    Ausgabe(s);
    fs.Read(s[0], Length(s));   // Hier knallt es
  finally
    fs.Free;
  end;
 
  ReadLn;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten