Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi [done] DEC class xy not found (https://www.delphipraxis.net/142709-%5Bdone%5D-dec-class-xy-not-found.html)

heri 2. Nov 2009 09:14


[done] DEC class xy not found
 
Hatte folgende Fehlermeldung vom DEC 5.2 nach dem Umstieg auf Delphi 2010: "class xy not found"

die Lösung (hier fett) lautet:

class function TDECObject.Identity: LongWord;
var
Signature: {$IFDEF UNICODE}AnsiString{$ELSE}String{$ENDIF};
begin
Signature := StringOfChar(#$5A, 256 - Length(Classname)) + UpperCase(ClassName); //°
Result := CRC32(IdentityBase, Signature[1], Length(Signature) * SizeOf(Signature[1]));
end;


man korrigiere mich bitte falls ich falsch liege.

himitsu 2. Nov 2009 09:44

Re: [done] DEC class xy not found
 
die/eine Lösung lautet nur
Zitat:

Signature: AnsiString;
PS: StringOfChar und UpperCase sind auch UnicodeFunktionen ... schau mal in Units wie AnsiStrings, ob es da AnsiVersionen gibt.

Aber ich war mir sicher, daß es hier auch irgendwo schon eine unicodefähige Version (D2009+) des DEC gibt.


aber eigentlich sieht es so aus, als wenn hier schon alles OK so war? :gruebel:
Code:
Result := CRC32(IdentityBase, Signature[1], Length(Signature) * [color=#ff0000]SizeOf(Signature[1])[/color]);

heri 2. Nov 2009 10:22

Re: [done] DEC class xy not found
 
ich habe diese Funktion jeweils unter D2006 und D2010 getestet und das Result waren jeweils unterschiedliche ID's - entsprechend konnte die Klasse natürlich nicht mehr gefunden werden

Zitat:

"Aber ich war mir sicher, daß es hier auch irgendwo schon eine unicodefähige Version (D2009+) des DEC gibt."
habe ich auch gedacht - muss es doch geben - aber wo?

himitsu 2. Nov 2009 11:03

Re: [done] DEC class xy not found
 
Daß es so unterschiedliche IDs ergibt, das ist schon klar, da die UnicodeDaten ja andere sind.

Aber dennoch sollte es funktionieren ... nur eben nicht Systemübergreifend :roll:



hmmmm ... also, da ClassName unter D2009+ auch Unicode ist und dies hier verwendeten Stringfunktionen auch, könnte es Probleme geben.
Aber wenn (da) der Klassenname nichts Exotisches ist, sollte es dennoch klappen (trotz der Unicode-Ansi-Umwandlung.
Delphi-Quellcode:
Signature: AnsiString;
sollte da vermutlich also schon ausreichen.

heri 2. Nov 2009 12:45

Re: [done] DEC class xy not found
 
ja, so funktionierts:

Delphi-Quellcode:
class function TDECObject.Identity: LongWord;
var
Signature: AnsiString;
begin
Signature := StringOfChar(#$5A, 256 - Length(Classname)) + UpperCase(ClassName); //° 
Result := CRC32(IdentityBase, Signature[1], Length(Signature) * SizeOf(Signature[1]));
end;
thx

Assertor 11. Mai 2010 15:46

Re: [done] DEC class xy not found
 
Hallo heri,

Zitat:

Zitat von heri
Delphi-Quellcode:
class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString;
begin
  Signature := StringOfChar(#$5A, 256 - Length(Classname)) + UpperCase(ClassName);
  Result := CRC32(IdentityBase, Signature[1], Length(Signature) * SizeOf(Signature[1]));
end;

SizeOf(Signature[1]) wird bei festem AnsiString nicht benötigt.

Ich arbeite gerade an der DEC 5.3, die Änderungen werde ich für Abwärtskompatibilität gerne übernehmen.

Gruß,
Assertor

himitsu 11. Mai 2010 16:03

Re: [done] DEC class xy not found
 
Warum eigentlich #$5A und nicht einfach 'Z' ?

Assertor 11. Mai 2010 16:07

Re: [done] DEC class xy not found
 
Zitat:

Zitat von himitsu
Warum eigentlich #$5A und nicht einfach 'Z' ?

;) Frag Hagen, möglich das früher Delphi das nicht geschluckt hat...

In der nächsten DEC wird es so gelöst:
Delphi-Quellcode:
class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString; // using ANSI to keep backward compatibility
begin
  // create signature ('Z' * n + 'TDECCLASSNAME')
  Signature := StringOfChar(AnsiChar(#$5A), 256 - Length(Classname)) +
               AnsiString(UpperCase(ClassName));
  // calc crc for signature
  Result := CRC32(IdentityBase, Signature[1], Length(Signature));
end;
Gruß,
Assertor

himitsu 11. Mai 2010 16:30

Re: [done] DEC class xy not found
 
Mir ist nix bekannt, warum 'Z' nicht gehn sollte. :gruebel:


Das müßte auch gehn,
Delphi-Quellcode:
uses ... {$if CompilerVersion >= 20.0}, AnsiStrings{$IFEND};

class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString; // using ANSI to keep backward compatibility
begin
  // create signature ('Z' * n + 'TDECCLASSNAME')
  Signature := StringOfChar('Z', 256 - Length(Classname))
    + UpperCase(AnsiString(ClassName));
  // calc crc for signature
  Result := CRC32(IdentityBase, Signature[1], Length(Signature));
end;
wobei es so wohl korrekter wäre
Delphi-Quellcode:
uses ... {$IF CompilerVersion >= 20.0}, AnsiStrings{$IFEND};

class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString; // using ANSI to keep backward compatibility
begin
  // create signature ('Z' * n + 'TDECCLASSNAME')
  Signature := StringOfChar('Z', 256 - Length(Classname))
    {$IF CompilerVersion >= 20.0}
      + UpperCase(UTF8Encode(ClassName));
    {$ELSE}
      + UpperCase(ClassName);
    {$IFEND}
  // calc crc for signature
  Result := CRC32(IdentityBase, Signature[1], Length(Signature));
end;
PS: AnsiStrings muß natürlich die letze Unit sein, bzw. zumindestens nach SysUtils stehen.

Warum Emba aber auch soein krankes Spiel mit den AnsiVersionen und mit den Namen der UnicodeVersionen spielen mußte.

function AnsiUpperCase(const S: string): string; ist doch wohl das Krankeste.



Und ich weiß grade nicht, ob im DEC eine *.INC für die CompilerVersionen enthalten ist.

Assertor 11. Mai 2010 16:38

Re: [done] DEC class xy not found
 
Hallo himitsu,

Zitat:

Zitat von himitsu
Mir ist nix bekannt, warum 'Z' nicht gehn sollte. :gruebel:

Das müßte auch gehn,
Delphi-Quellcode:
uses ... {$if CompilerVersion >= 20.0}, AnsiStrings{$IFEND};

class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString; // using ANSI to keep backward compatibility
begin
  // create signature ('Z' * n + 'TDECCLASSNAME')
  Signature := StringOfChar('Z', 256 - Length(Classname))
    + UpperCase(AnsiString(ClassName));
  // calc crc for signature
  Result := CRC32(IdentityBase, Signature[1], Length(Signature));
end;

Richtig, ist aber faktisch kein Unterschied und man spart nur ein AnsiChar() - dafür muß man aber IFDEFen und eine weitere Unit einbinden.

Zitat:

Zitat von himitsu
wobei es so wohl korrekter wäre
Delphi-Quellcode:
uses ... {$IF CompilerVersion >= 20.0}, AnsiStrings{$IFEND};

class function TDECObject.Identity: LongWord;
var
  Signature: AnsiString; // using ANSI to keep backward compatibility
begin
  // create signature ('Z' * n + 'TDECCLASSNAME')
  Signature := StringOfChar('Z', 256 - Length(Classname))
    {$IF CompilerVersion >= 20.0}
      + UpperCase(UTF8Encode(ClassName));
    {$ELSE}
      + UpperCase(ClassName);
    {$IFEND}
  // calc crc for signature
  Result := CRC32(IdentityBase, Signature[1], Length(Signature));
end;
PS: AnsiStrings muß natürlich die letze Unit sein, bzw. zumindestens nach SysUtils stehen.

Jein. UTF8Encode könnte ja theoretisch den Wert ändern - es geht ja gerade darum, diesen in allen Delphis absolut identisch zu haben. Wobei bei UTF8Encode der ASCII Bereich ja kein Problem darstellt...

Zitat:

Zitat von himitsu
Warum Emba aber auch soein krankes Spiel mit den AnsiVersionen und mit den Namen der UnicodeVersionen spielen mußte.

function AnsiUpperCase(const S: string): string; ist doch wohl das Krankeste.


Und ich weiß grade nicht, ob im DEC eine *.INC für die CompilerVersionen enthalten ist.

Jaja, die Unicode Umstellung war schon was tolles. Und die ganzen halbherzigen Komponenten Portierungen auch (wo nur String > AnsiString und Char > AnsiChar geändert wurde) :mrgreen:

Jup, im neuen DEC 5.3 kommt ein Include was automatisch für alte, jetzige und neue Versionen stimmt. Ist schon fertig.

Gruß,
Assertor

negaH 12. Mai 2010 20:55

Re: [done] DEC class xy not found
 
Zitat:

Warum eigentlich #$5A und nicht einfach 'Z' ?
Kannst du erkennen das im Zeichen Z das oberste Nibble 0101b=$5 und das unterste Nibble 1010b=$A ist ?

Es wird also deshalb #$5A benutzt weil es um die binäre Codierung hier geht die der Programmierer benutzen möchte. Ich nenne es "explizite Programmierung" und deren Ziel ist die Reproduzierbarkeit der Sourcen im Kopf anderer Programmierer.

Gruß Hagen

himitsu 12. Mai 2010 21:01

Re: [done] DEC class xy not found
 
Jetzt wo du's sagst ... daran hatte ich garnicht gedacht :oops: (hatte nur beim Anblick des Wertes das Z vor Augen)
aber stimmt, dann ist es so natürlich besser.


Schade, daß es in Delphi keine Binärdarstellung gibt.

negaH 12. Mai 2010 21:15

Re: [done] DEC class xy not found
 
nochwas zum Thema .Identity im DEC. Das ist eine der Stellen dir mir so garnicht noch nie richtig gefallen hat ;)
Die zu lösende Problematik ist eine möglichst kurze aber eineindeutige ID zu jeder Klasse im DEC zu schaffen. Wichtig dabei ist aber noch das man mit der Änderung von DECUtil.IdentityBase alle IDs serialisieren kann. Dh. je nach Anwendung kann der Programmierer über IdentityBase das ID System individualisieren auf ein Projekt ohne das man den kompletten Source ändern muß.

Man speichert also in einem Stream als Header die Identities der benutzten DEC Klassen und danach zb. die verschlüsselten Daten. Bei der Entschlüsselung kann mit DECClassByIdentity() diese registrierte Klasse als Objekt geladen werden. Um diese Header mit fester Länge anlegen zu können wird für Identity ein Cardinal benutzt, statt wie üblich den Klassennamen im Header lesbar zu speichern.

Ein weiteres Kriterium war dabei aber auch das zukünftige neue DEC Klassen voll transparent implementierbar sein müssen ohne das sich der jeweiligen Programmierer mit diesen IDs beschäftigen müssen. Zb. bei Vergabe fester sequentieller IDs für die Klassen müssen die Programmierer sich immer abstimmen und diese IDs dann auch pflegen. Das geht bei einer Bibliothek die weltweit verwendet wird leider nicht mehr zu organisieren.

Jetzt, im nachhinein, würde ich GUIDs dafür benutzen da man damit schon rein mathematisch die Wahrscheinlichkeiten von Kollisionen enorm reduziert. Das jetztige Verfahren birgt ein hohes Risiko von Kollisionen, die aber bei der Registration einer DEC Klasse zuverlässig erkennt werden. Sollte dies der Fall sein muß man entweder den Klassennamen oder IdentityBase ändern.

Wie gesagt, damals viel mir nichts besseres ein und zufrieden bin ich mit dieser Lösung noch heute nicht. Vielleicht fällt ja einem von euch was ein was neu für mich wäre.

Gruß Hagen

Assertor 14. Mai 2010 11:49

Re: [done] DEC class xy not found
 
Hallo Hagen,

Zitat:

Zitat von negaH
Wie gesagt, damals viel mir nichts besseres ein und zufrieden bin ich mit dieser Lösung noch heute nicht. Vielleicht fällt ja einem von euch was ein was neu für mich wäre.

Eine GUID Liste zu führen und abzugeleichen wäre tatsächlich zu aufwendig und fehleranfällig. Eine langsamere Alternative wäre die Nutzung von Hashes, also ein Hash auf Klassenname + IdentityBase. Die verwendete Hash-Klasse könnte dann, wie IdentityBase, änderbar sein und das Default entsprechend Weise gewählt werden. Genauso wie eine GUID bekommt man das natürlich nicht mehr in einem LongWord/Cardinal unter, sondern würde entspreche Wrapper für .Identity als Bytes und zusätzlich z.B. als HEX-String bieten.

Es gäbe dabei aber das Problem der Abwärtskompatibilität, da die jetzige Identity ja auch von Entwicklern genutzt wird. Eine Änderung könnte m.E. nur parallel implementiert werden.

Gruß,
Assertor

P.S.: Meine PN bezgl. 2DES/3DES und Byte Arrays hat sich vollkommen erledigt - läuft alles :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:04 Uhr.

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