Linux <-> Windows Datenkompatibilität

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Linux <-> Windows Datenkompatibilität

Beitrag von CPU-Quaeler »

Hallo Leute!

Ich habe im Moment ein Problem, was mich sehr nevt. Ich schreibe ja mit dem Euklid an Promathika und wir nähern uns an die Version 1.0. Das Problem an dem Programm ist, dass es Linux- und Windows-Versionen geben wird, die aber absolut kompatible Dateien (Settings, Funktionslisten...) erzeugen sollen, damit hier keine extra Unterscheidung notwendig ist.

Ich erzeuge zum Speichern von Settings und Listen Dateien von bestimmten Records. Das funktioniert auch wunderbar, solange man Linux-Dateien in der Linux-Version öffnet und Windows-Dateien in der Windows-Version. Es funktioniert aber nicht, wenn ich eine in Windows erzeugte Settings-Datei in Linux aufrufen möchte oder umgekehrt. Hier ist die Record-Definition:

Code: Alles auswählen

type tColorSettings=record
    bgrdCol:tColor;
    bgrdCol2:tColor;
    CurvCol:tColor;
    CurvCol2:tColor;
    GridCol:tColor;
    PinCol: tColor;
    AxisCol:tColor;
    AxisCrossCol:tColor;
    RulBgrdCol:tColor;
    RulTextCol:tColor;
    BgrdGrad:ShortInt; //Hintergrundfarbverlauf  -1=aus; 0=vertical; 1=horizontal
    CurvGrad:ShortInt; //Funktionsfarbverlauf  -1=aus; 0=vertical; 1=horizontal
  end;
 
  type tPerformanceSet=record
    ThreadCount:byte;   //Anzahl der Threads für Graphberechnung
    CurvWidth:double;    //Strichbreite für Graphen
    AA_Level_hor:byte;  //horizontale Subpixel-Anzahl
    AA_Level_ver:byte;  //vertikale Subpixelanzahl
    unsharpness:extended;    //Schritweite in Hauptachsen-Richtung
    TermOut:ShortInt;       //-1=aus; 0=einfach; 1=komplex
    TermkoordX:integer;    //X-Koordinate für linke obere Ausgabe-Ecke von Termen
    TermKoordY:integer;    //Y-Koordinate
    statistics:boolean;
    AA_Mode:word;
  end;
 
  type tKartesianSet=record
    xmin:extended;
    xmax:extended;
    ymin:extended;
    ymax:extended;
    DistortFree:ShortInt;//-1=aus;0=xmin variabel; 1=xmax variabel; 2=ymin variabel; 3=ymax variabel
    AxisSign:boolean;
    Ruldens_X:double;
    Ruldens_Y:double;
    GridDensX:double;
    GridDensY:double;
    PinSubDensX:double;
    PinSubDensY:double;
    RulerMode:ShortInt; //-1=aus; 0=angepasst; 1=benutzerdefinierter Hintergrund
  end;
 
  type tMainSizing=record
    MainWidth:word;
    MainHeight:word;
    DrawResX:word;
    DrawResY:word;
  end;
 
  type tGlobalSet=record
    ColorSet:tColorSettings;
    PerformanceSet:tPerformanceSet;
    Kartesianset:tKartesianSet;
    MainSizing:tMainSizing;
  end;
Die Settings-Datei zum Beispiel ist vom Typ tGlobalSet, der als letztes aufgeführt ist und alle vorherigen enthält. Nachfolgend sind die functions zum Laden und Speichern von Einstellungen:

Code: Alles auswählen

function tFMain.LoadSet (var loc_Set:tGlobalSet):boolean;
 var
   Filestring:string;
   DefaultSet:File of tGlobalSet;
   fileClosed:boolean=false;
  begin
    FileString:='defaults.prs';
    try
      AssignFile(DefaultSet,FileString);
      {$i-}
      Reset(DefaultSet);
      {$i+}
      Seek(DefaultSet,0);
      read(DefaultSet,Loc_Set);
      CloseFile(DefaultSet);
      result:=true;
      FileClosed:=true;
    except
      result:=false;
      loc_set:=prm_setmanager.get_Defaults;
      If not FileClosed then CloseFile(DefaultSet);
    end;
  end;
 
//==========================================================================================
 
function tFMain.SaveSet (loc_set:tGlobalSet):boolean;
 var
   Filestring:string;
   DefaultSet:File of tGlobalSet;
   FileClosed:boolean=false;
  begin
    FileString:='defaults.prs';
    try
      AssignFile(DefaultSet,FileString);
      {$i-}
      ReWrite(DefaultSet);
      {$i+}
      Seek(DefaultSet,0);
      write(DefaultSet,Loc_Set);
      CloseFile(DefaultSet);
      result:=true;
      FileClosed:=true;
    except
      result:=false;
      If not FileClosed then CloseFile(DefaultSet);
    end;
  end;
Vielen Dank vorab! Falls ich Infos vergessen habe, werde ich diese mit Vergnügen nachreichen.
Zuletzt geändert von monta am Fr 11. Sep 2009, 00:43, insgesamt 1-mal geändert.
Grund: Codetags

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Linux <-> Windows Datenkompatibilität

Beitrag von theo »

Vllt mal mit "packed" probieren
type tColorSettings=packed record ...
etc.

Anonsten schauen wo Unterschiede sind, z.B. mal alles auf beiden Systemen mit SizeOf Ausgeben lassen:
Writeln(SizeOf(tMainSizing));
Writeln(SizeOf(tColorSettings));
etc.

CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Re: Linux <-> Windows Datenkompatibilität

Beitrag von CPU-Quaeler »

theo hat geschrieben:Vllt mal mit "packed" probieren
type tColorSettings=packed record ...
etc.

Anonsten schauen wo Unterschiede sind, z.B. mal alles auf beiden Systemen mit SizeOf Ausgeben lassen:
Writeln(SizeOf(tMainSizing));
Writeln(SizeOf(tColorSettings));
etc.
Danke für die schnelle Antwort. Ich habs mal ausprobiert.
Windows (nicht packed)
tGlobalSet ~ 200 byte
tkartesianSet ~ 96 byte
tPerformanceSet ~ 48 byte
tColorSettings ~ 44 byte
tMainSizing ~ 8 bytes
=> tGlobalSet müsste 196 byte groß sein, ist aber 200 bytes. Wenn ich das tGlobalSet als Packed ansetze, bekomme ich 196 bytes. Wenn ich aber davon ausgehe, wie die Standard-Typen definiert (Word=2 byte, ShortInt=1byte, byte=1 byte, boolean=1 byte, double= 8 byte, extended=10 byte, dword und longInt=4 byte) sind, müsste ich schon pro selbstdefiniertem Typ viel weniger haben...ich krieg Haarausfall :mrgreen: Wenn ich jeden record packed mache, gibts sehr lustige Fehler

Wenn ich nun das ganze in Linux teste, bekomme ich noch größere Größen. tGlobalSet nicht packed = 256 byte, packed 244 byte. Aber immerhin tColorSettings (44 byte) und tMainSizing (8 byte) sind in Linux und Windows (beides übrigens 64bit mit 64bit-Lazarus und gleiche Snapshot) gleich groß...das ist doch mal ein kleiner Sieg! :D tMainSizing stimmt sogar mit den theoretischen 8 byte überein. tColorSettings hätte ich so rein theoretisch 42 byte zugetraut, aber nicht 44. Öhm...ja. Bitte sag einer, dass ich nicht am Rad drehe, sonst glaub ichs noch am Ende :?:

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Linux <-> Windows Datenkompatibilität

Beitrag von theo »

Weiss nicht, ich würde das aber auch nicht so serialisieren.
Einfache Typen speichern (Byte, Word, Longint, String etc,). Records, Sets und sonstige Typen wären mir zu unsicher.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Linux <-> Windows Datenkompatibilität

Beitrag von Euklid »

CPU-Quaeler hat geschrieben: Öhm...ja. Bitte sag einer, dass ich nicht am Rad drehe, sonst glaub ichs noch am Ende :?:
Du drehst am Rad :p
theo hat geschrieben:Einfache Typen speichern (Byte, Word, Longint, String etc,). Records, Sets und sonstige Typen wären mir zu unsicher.
Hmm... Du meinst, wir sollten anstatt das Record als Ganzes lieber die im Record zusammengefassten Variablen sozusagen "einzeln" speichern?

Gruß, Euklid

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Linux <-> Windows Datenkompatibilität

Beitrag von theo »

Euklid hat geschrieben: Hmm... Du meinst, wir sollten anstatt das Record als Ganzes lieber die im Record zusammengefassten Variablen sozusagen "einzeln" speichern?
So mach ich das meistens. Das müsste dann auch mit Delphi oder C etc. gelesen werden können, da die Datengrössen eindeutig sind und das Dateiformat somit "dokumentierbar". XML ginge auch.
Evtl. kann auch der da helfen: http://www.lazarusforum.de/viewtopic.php?p=2108#p2108" onclick="window.open(this.href);return false;

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Linux <-> Windows Datenkompatibilität

Beitrag von mse »

Neben XML kämen auch Inifiles und Komponenten streaming durch TReader/TWriter in Frage falls tGlobalSet als TPersistent Klassenabkömmling implementiert würde. Die Serialisierung von published properties würde dabei vom Compiler und der RTL übernommen.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Linux <-> Windows Datenkompatibilität

Beitrag von Euklid »

Danke für Eure Antworten!

CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Re: Linux <-> Windows Datenkompatibilität

Beitrag von CPU-Quaeler »

Danke, dass du dich für mich bedankst, Euklid! :D

Wir werden die Variante mit der Text-Datei (oder ini, oder wie auch immer man die nennen mag) verwenden zum Speichern von Einstellungen und vermutlich auch zum Speichern von Funktionslisten. Finde ich sehr schade, dass das mit den Records nicht Linux-Windows-kompatibel ist, denn es funktioniert wirklich einfach, solange man nicht das OS wechselt. Jetzt muss ich doch mit Strings wurschteln...habe mich solang, wies geht , davor gedrückt. In C kann man wenigestens String tanga schreiben...in fp geht nur tanga:string :roll:

Danke für eure Vorschläge!

(P.s.: Solange man in den Records Variablen gleichbleibender Größe verwendet, funktionierts, aber das bringt mir wenig)

_Bernd
Beiträge: 145
Registriert: Di 13. Feb 2007, 11:16

Re: Linux <-> Windows Datenkompatibilität

Beitrag von _Bernd »

CPU-Quaeler hat geschrieben:...Finde ich sehr schade, dass das mit den Records nicht Linux-Windows-kompatibel ist, denn es funktioniert wirklich einfach, solange man nicht das OS wechselt. Jetzt muss ich doch mit Strings wurschteln...
Wenn man die Records als packed deklariert muß es eigentlich gehen. Andernfalls wäre es IMHO ein Bug.
Zumindest unter 32-Bit Windows und Linux erhalte ich dann korrekte und identische Längen für die einzelnen Records:

tPerformanceSet: 33
tKartesianSet: 91
tMainSizing: 8
tColorSettings: 42

Gesamt: 174

Bei nicht packed deklarierten Records differieren die Recordlängen zwischen Linux und Windows tatsächlich. Das finde ich als Laie eigentlich erstaunlich. Man könnte mal auf der Mailingliste nachfragen, warum das so ist. Für 64-Bit Linux/Windows kann ich es momentan nicht testen.

Gruß, Bernd.

Socke
Lazarusforum e. V.
Beiträge: 3178
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: Linux <-> Windows Datenkompatibilität

Beitrag von Socke »

_Bernd hat geschrieben:Bei nicht packed deklarierten Records differieren die Recordlängen zwischen Linux und Windows tatsächlich. Das finde ich als Laie eigentlich erstaunlich.
Der Compiler richtet die einzelnen Felder eines Records (oder einer Klasse) automatisch im Speicher aus um die Zugriffszeiten zu optimieren. Das Schlüsselwort packed heißt eigentlich nur, dass die Felder nicht ausgerichtet werden sondern direkt hintereinander.
Wenn die gleichen Compiler-Optionen (bezüglich Records) verwendet werden, sollten die Größen aber eigentlich architekturübergreifend gleich bleiben :roll:

Zum Speichern von Einstellungen gibt es bereits fertige Klassen, die alles automatisch machen. Alles was man braucht ist der Schlüssel. Dann kann alles direkt auslesen/speichern. Für XML-Dateien empfehle ich TXMLConfig. Die Typkonvertierung erfolgt bei Benutzung der entsprechenden Methoden automatisch.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten