Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Move Anweisung (https://www.delphipraxis.net/155632-move-anweisung.html)

MrSpock 1. Nov 2010 19:33

Delphi-Version: 2010

Move Anweisung
 
Ich habe ein interessantes Problem beim Umstellen auf D2010. In dieser Version ist ein Char ja 2 Bytes groß. Ich lese aus der Sage CL 2010 Datensätze aus. Dort ist ein Char noch 1 Byte groß, was ich mit einem Hexeditor geprüft habe. Ich habe jetzt Records angelegt, damit ich auf die Daten über ihre Namen / Bedeutungen zugreifen kann: Beispiel:

Delphi-Quellcode:
TCl4_a10110 = record      { Kundenstamm }
   case boolean of
   true : (
      Anzahl_valid_records : array[1..6] of Char;
      Gesamtzahlrecords : array[1..6] of Char;
      Recordlaenge : array[1..4] of Char;
                Ueberhang: array[1..6] of Char;
      Headerrest  : array[1..cl4_a10110Recordlaenge
                        -Headerlaenge] of Char);
   false : (
    {1}   Kundennummer   : array[1..10] of Char ;
         {11}   Name1           : array[1..50] of Char;
    {61}   Name2           : array[1..50] of Char;
   {111}   Strasse        : array[1..50] of Char;
   {161}   Plz_Ort        : array[1..45] of Char;
   {206}   Vertreter      : array[1..3] of Char;
...
Dann lasse ich mir den Puffer von dem Sage CL 2010 COM-Object zurückgeben und merke mir einen Zeiger darauf.
Dann kommt die Move Anweisung:

Delphi-Quellcode:
Move(A10110.Buffer^, Kunde, cl4_a10110Recordlaenge)
Kunde ist vom Typ TCl4_a10110. Ich dachte, das könne nicht funktionieren, weil z.B. das Feld Name jetzt pro Char doppelt so groß ist wie der Char aus Sage. Also habe ich aus Char im oben definierten Typ ein AnsiChar gemacht. Dann steht aber nach dem Move nur noch Müll in "Kunde". Lasse ich aber die Definition wie sie ist, funktioniert es!? :gruebel:

Ich habe mir mal die Länge von TCL14_a10110 ausgeben lassen und diese ist tatsächlich fast doppelt so lang wie vorher, was zeigt, dass ein Char auch wirlich als 2 Bytes dargestellt wird.

Die Move Anweisung arbeitet doch einfach Byte-weise oder erkennt diese, dass in der Destination ein Array of Char wartet und macht dann die Anpassung automatisch!? Oder woran liegt es, dass es mit der "falschen" Char Größe funktioniert?

himitsu 1. Nov 2010 20:31

AW: Move Anweisung
 
Jupp, System.Move arbeitet byteweise, aber eventuell konvertiert Sage CL die Datensätze.

MrSpock 1. Nov 2010 20:43

AW: Move Anweisung
 
Hallo himitsu,

danke erstmal.

Bin jetzt einen Schritt weiter. Noch tiefer unten im Sumpf der COM-Objekte gibt es Anweisungen der Form:

Delphi-Quellcode:
procedure myKHKbinRead (ObjFileIO : _CFileIO;
           ichannel,
                        ikeyOffset : SmallInt;
              sKey :WideString;
                        sbuffer :Pchar;
                        var irecNb: LongInt);
var
   StrBuffer : AnsiString;
begin
   ObjFileIO.objFile(iChannel).binRead (ikeyOffset ,sKey, irecNb);
   strBuffer := ObjFileIO.objFile(iChannel).strGetFieldBuffer
      (1,ObjFileIO.objFile(iChannel).lngRecordLen);
   if irecNb > 0 then
      Move(StrBuffer[1],sBuffer^,ObjFileIO.objFile(iChannel).lngRecordLen);
end;
Der StrBuffer war bisher als String definiert. Die Funktion ObjFileIO.objFile(iChannel).strGetFieldBuffer gibt aber einen WideString zurück (wie bei COM Objekten üblich). Hier wurde also früher die Konvertiereung zurück in "Small" Strings durchgeführt. Jetzt habe ich dort String durch AnsiString ersetzt (und in allen anderen Lesefunktionen auch) und jetzt sieht es gleich wieder besser aus, wenn ich auch in TCl4_a10110 alle Strings durch AnsiStrings ersetze. :cyclops:

himitsu 1. Nov 2010 20:57

AW: Move Anweisung
 
Wenn du jetzt Unicode zur Verfügung hast, dann könntest du dieses ja nun auch nutzen?

Also alles zurück auf String und dann vermutlich noch diese Stelle anpassen:
Delphi-Quellcode:
Move(StrBuffer[1], sBuffer^, ObjFileIO.objFile(iChannel).lngRecordLen * SizeOf(Char));
Also ich hätte hier erwartet, daß die letzte Hälfte der Datensätze unter Unicode fehlt.

MrSpock 1. Nov 2010 21:15

AW: Move Anweisung
 
Nein, das funktioniert so nicht, weil in dem Record ja auch andere Typen sind. Wenn ich nicht die Rückverwandlung in kurze Strings durchführe, weiß ich nicht, was mit den anderen Typen bei der Übergabe passiert. Wie gesagt intern arbeitet die CL weiterhin mit 1 Byte Char.

himitsu 1. Nov 2010 21:27

AW: Move Anweisung
 
OK, der TCl4_a10110 bestand ja nur aus Char, da wäre es gegangen.

Also, aus einem Delphi-Referenz durchsuchenByte würde ein Delphi-Referenz durchsuchenWord, aber größere Typen würden nicht funktionieren

Word würde so zu LongWord, aber aus $xxyy würde $00xx00yy :stupid:

Wobei ich bei allen Werten über $7f, 127 und #127 aufpassen würde, da diese bei einer Unicode>Ansi-Umwandlung zerstört werden könnten, wenn eine andere Codepage genutzt würde, welche genutzt wurde, um auf der anderen Seite der COM-Schnittstelle die Bytes nach WideString zu konvertieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz