Alte .lib aus BCB6 in CG2009
-
Hallo zusammen
Ich habe eine alte .lib Datei, welche mit dem BCB6 erstellt wurde.
Diese Lib kann ich mit dem BCB6 problemlos in ein Projekt linken.
Wenn ich dies allerdings mit dem CG2009 versuch kommt immer:[ILINK32 Fehler] Error: Nicht auflösbares externes 'BugyCheckMd5FromFile(System::AnsiStringT<0>)' referenziert von C:\PROJECTS\_CPP\Z_TEST\ZLIBTESTMD5\DEBUG\UNIT3.OBJ
Kann dies überhaupt funktionieren, oder hat es etwas mit der Umstellung des CG2009 auf Unicode zu tun?
Vielen Dank im voraus.
MfG Stephan
-
Stephan schrieb:
Kann dies überhaupt funktionieren, oder hat es etwas mit der Umstellung des CG2009 auf Unicode zu tun?
Ja. Die Dokumentation gibt dazu genauer Auskunft:
How to Handle Delphi AnsiString Code Page Specification in C++ schrieb:
The C++ implementation of the AnsiString type provides CodePage support similar to that available in Delphi 2009. However, while the Delphi version is implemented via extension to the language, the C++ version is implemented via a template with a non-type parameter as codepage, as in:
template AnsiStringT<unsigned short codePage>
Therefore, the type previously known as AnsiString type is now simply a typedef of the new AnsiStringT template, as in:
typedef AnsiStringT<65001> UTF8String; typedef AnsiStringT<65535> RawByteString;
You can declare other specializations of AnsiStringT with the codepage you need.
[...]Die Konsequenz ist natürlich, daß das Name-Mangling für AnsiString abweicht. Du wirst die Bibliothek also neu kompilieren müssen (was auch anderer Abweichungen wegen sinnvoll ist).
-
Hallo zusammen
@audacia
Also ich habe dies vereinfacht so verstanden:
Die Implementierung des Typ AnsiString hat sich zwischen BCB6 und CG2009 geändert. Aus diesem Grund kann die Lib nicht gelinkt werden und muß wenn sie in CG2009 verwendet werden soll neu compiliert werden.Wenn dies wirklich so ist, dann habe ich ein Problem, da ich die Lib vermutlich nicht mehr kompilieren kann.
Das muß ich mir dann wohl nochmals genauer anschauen.Danke.
MfG Stephan
-
Stephan schrieb:
Die Implementierung des Typ AnsiString hat sich zwischen BCB6 und CG2009 geändert. Aus diesem Grund kann die Lib nicht gelinkt werden und muß wenn sie in CG2009 verwendet werden soll neu compiliert werden.
So ist es.
-
Hatte auch so ein Problem bei der Portierung einer lib,
habe dann aus der lib eine DLL gemacht und greife nun
über die DLL auf die Funktionen zu.
-
VergissEs schrieb:
habe dann aus der lib eine DLL gemacht und greife nun
über die DLL auf die Funktionen zu.Selbst damit verläßt du dich darauf, daß die Implementation von AnsiString auf beiden Seiten gleich ist, was keineswegs immer der Fall sein muß. Mit der Unicode-Umstellung wurde z.B. die internen Felder (untergebracht bei negativen Indizes; für Details siehe AnsiString::StrRec) angepaßt. Ich bin nicht sicher, was passiert, wenn die String-Checks, die C++Builder >=2009 durchführt, auf einem AnsiString durchgeführt werden, der die internen Felder alten Stils besitzt, aber es dürfte nicht besonders hübsch sein.
Viel schlimmer wird das natürlich, wenn zusätzlich noch STL-Typen verwendet werden: C++Builder 6 verwendet STLport, alle nachfolgenden Versionen bis einschließlich 2010 enthalten Dinkumware; die beiden sind natürlich grundsätzlich inkompatibel.
Merke: zwischen Modulen, die mit verschiedenen Compilern oder auch nur abweichenden Compilerversionen erstellt wurden, nur über C-Interfaces kommunizieren. Das gilt für alle Arten der Module, also für Objektdateien (.obj) und Sammlungen derselben (.lib) gleichermaßen wie für DLLs.
Die saubere Lösung ist natürlich, die Bibliotheken mit C++Builder 2009 zu übersetzen. Woran scheitert das?
-
Im meinem Fall ist es die Jedi Komponente
TJvZlibMultiple die Ihren Dienst nicht mehr unter 2009 tut.
-
VergissEs schrieb:
Im meinem Fall ist es die Jedi Komponente
TJvZlibMultiple die Ihren Dienst nicht mehr unter 2009 tut.Deshalb machst du dir derartige Umstände? Du könntest einfach den Code in JvZlibMultiple.pas anpassen; wie hier und hier unter anderem beschrieben wird, dürfte es schon ausreichen, überall dort, wo Strings in die einzelnen Bytes zerlegt oder in Streams geschrieben werden (also dort, wo
SizeOf(Char)=1
impliziert wird), Char durch AnsiChar und String durch AnsiString zu ersetzen. Und wenn es funktioniert, könntest du den Bug sowie einen Workaround in den JEDI Issue Tracker eintragen, dann werden deine Änderungen auch in die offizielle JVCL-Revision aufgenommen.
-
Ja ich machte mir diese Umstände weil ich Gewährleisten muss das schon
bestehende Archive auch weiterhin gelesen werden müssen.
Und da ich meine Anwendungen komplett auf UnicodeString
umgestellt habe kommt auch nicht einChar durch AnsiChar und String durch AnsiString zu ersetzen
in Frage.
-
VergissEs schrieb:
Und da ich meine Anwendungen komplett auf UnicodeString
umgestellt habe kommt auch nicht einChar durch AnsiChar und String durch AnsiString zu ersetzen
in Frage.
Das sollte davon nicht tangiert werden. In diesem Fall ist es ja kein Quick&Dirty-Fix, sondern die Komponente benutzt Strings anstelle von Byte-Arrays. Und da sind nunmal AnsiStrings richtig, da ihre Elementgröße 1 ist.
-
audacia schrieb:
Das sollte davon nicht tangiert werden. In diesem Fall ist es ja kein Quick&Dirty-Fix, sondern die Komponente benutzt Strings anstelle von Byte-Arrays. Und da sind nunmal AnsiStrings richtig, da ihre Elementgröße 1 ist.
Es müsste aber ein Quick&Dirty-Fix daraus gemacht werden um weiterhin Dateien zu öffnen die mit AnsiString Dateinamen gespeichert wurden und nun auch Unicode Dateinamen zulässig sein sollen.
-
Daß das Dateiformat beibehalten werden muß, sehe ich nicht als "quick&dirty" an. Und wenn du Unicode-Unterstützung willst, wäre es denkbar, das Dateiformat rückwärtskompatibel zu erweitern. Beispiel: wenn die Strings mit 0xEE 0xBB 0xBF beginnen, sind sie UTF-8-codiert.
-
Hallo zusammen
Merke: zwischen Modulen, die mit verschiedenen Compilern oder auch nur abweichenden Compilerversionen erstellt wurden, nur über C-Interfaces kommunizieren. Das gilt für alle Arten der Module, also für Objektdateien (.obj) und Sammlungen derselben (.lib) gleichermaßen wie für DLLs.
Wenn ich dies richtig verstehe, kann ich unter BCB6 eine lib erstellen welche intern den "alten" AnsiString verwendet, nur die Parameter sollten von AnsiString auf char* umgestellt werden.
Das kompilieren unter CG2009 habe ich versucht, war jedoch nicht erfolgreich.
Kurz zur Vorgeschichte/Erklärung:
Ich habe als der BCB6 neu war ein Programm erstellt, welches einen MD5 Hash über Dateien rechnet und prüft (Hash wird anschließend in diese Datei geschrieben).
Hierfür wurde damals der MD5Coder von Indy8 verwendet. Das der Md5Coder einen Bug hat und keinen "echten" MD5 Hash errechnet ist damals nicht aufgefallen, da der Hash mit der gleichen Komponente erstellt und geprüft wurde.
Mit Indy9 kam dann die Ernüchterung und es wurde klar, daß Indy8 hier einen Bug hat. Also lib mit Indy8 erstellt und zukünftig diese immer als Workaround verwendet.
Das das komplette Programm nun auf CG2009 umgestellt werden soll, habe ich nun das Problem, daß ich den Indy8 Md5Coder irgendwie mit CG2009 zum laufen bekommen muß.Unter BCB6 lässt sich alles kompilieren, jedoch beim CG2009 bekomme ich nun diese Fehler:
[DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt. Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht. [DCC Warnung] idglobal_V8.pas(616): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt. Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht. [DCC Warnung] idglobal_V8.pas(764): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt. Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht. [DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString' [DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string' [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::~TCustomOutline()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::TCustomOutline(Classes::TComponent *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetOutlineStyle(Outline::TOutlineStyle)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetOutlineOptions(System::Set<Outline::TOutlineOption, 0, 2>)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::GetPicture(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetPicture(int, Graphics::TBitmap *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetFullPath()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::HasChildren()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::getFirstChild()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetNextChild(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Insert(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetLastChild()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Add(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::AddChild(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Get(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Clear()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::SetExpandedState(bool)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetSelectedItem(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Click()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::GetSelectedItem()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Expand(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Loaded()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes 'Outline::TCustomOutline::' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::DefineProperties(Classes::TFiler *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::DrawCell(int, int, const Types::TRect&, System::Set<Grids::Grids__3, 0, 2>)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__tpdsc__ Outline::TCustomOutline' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetItemHeight(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::StoreBitmap(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetStyle(Outline::TOutlineType)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
Das komplette kompilieren unter CG2009 wäre mir auch am liebsten.
Irgendwelche Anregungen?MfG Stephan
-
Hallo zusammen
Also nach etwas auprobieren kann ich nun die ganze Sache kompilieren.
Das Projekt (Fehler von vorherigem Post) war eine DLL und nachdem ich daraus eine Exe gemacht habe hat's funktioniert. Siehe auch http://www.marquardtnet.info/cecke/quickies.1/1_quicky_43.html Lösung 3.Allerdings stimmt nun die Berechnung des MD5 Hash aus Indy8 nicht mehr.
Kann mir eventuell jemand etwas zu den Warnings sagen, habe von Delphi leider keine Ahnung.[DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt. Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
class procedure TIdURI.NormalizePath(var APath: string); var i: Integer; begin i := 1; while i <= Length(APath) do begin if APath[i] in LeadBytes then //Zeile 58 begin inc(i, 2) end else if APath[i] = '\' then begin APath[i] := '/'; inc(i, 1); end else begin inc(i, 1); end; end; end;
[DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString'
function URLDecode(psSrc: string): string; var i: Integer; ESC: string[2]; CharCode: integer; begin Result := ''; { do not localize } psSrc := StringReplace(psSrc, '+', ' ', [rfReplaceAll]); {do not localize} i := 1; while i <= Length(psSrc) do begin if psSrc[i] <> '%' then { do not localize } begin {do not localize} Result := Result + psSrc[i] end else begin Inc(i); ESC := Copy(psSrc, i, 2); //Zeile 988 Inc(i, 1); try CharCode := StrToInt('$' + ESC); {do not localize} if (CharCode > 0) and (CharCode < 256) then Result := Result + Char(CharCode); except end; end; Inc(i); end; end;
[DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string'
function URLDecode(psSrc: string): string; var i: Integer; ESC: string[2]; CharCode: integer; begin Result := ''; { do not localize } psSrc := StringReplace(psSrc, '+', ' ', [rfReplaceAll]); {do not localize} i := 1; while i <= Length(psSrc) do begin if psSrc[i] <> '%' then { do not localize } begin {do not localize} Result := Result + psSrc[i] end else begin Inc(i); ESC := Copy(psSrc, i, 2); Inc(i, 1); try CharCode := StrToInt('$' + ESC); {do not localize} //Zeile 991 if (CharCode > 0) and (CharCode < 256) then Result := Result + Char(CharCode); except end; end; Inc(i); end; end;
Vielen Dank im voraus.
MfG Stephan
-
Stephan schrieb:
Wenn ich dies richtig verstehe, kann ich unter BCB6 eine lib erstellen welche intern den "alten" AnsiString verwendet, nur die Parameter sollten von AnsiString auf char* umgestellt werden.
Ja.
Stephan schrieb:
Kann mir eventuell jemand etwas zu den Warnings sagen, habe von Delphi leider keine Ahnung.
(Das würde ich dringend ändern. Delphi-Kenntnis ist für C++Builder-Programmierer von entscheidendem Vorteil.)
Stephan schrieb:
[DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt. Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
Was ein Set ist, dürfte dir aus C++Builder bekannt sein. In Delphi ist das ein intrinsischer Typ, z.B.:
type TOrdinal = (One, Two, Three); TOrdinals = set of TOrdinal; const SomeOrdinals: TOrdinals = [One, Three];
Aber auch:
type TSysCharSet = set of AnsiChar; const AlphaNumericChars: TSysCharSet = ['A'..'Z', 'a'..'z', '0'..'9', '_']; WhitespaceChars = [' ', #09];
Wie im letzten Beispiel ersichtlich, kann die explizite Typangabe auch weggelassen werden; der Compiler deduziert den Typen dann anhand der Elementtypen.
Hier liegt nun das Problem: seit Delphi 2009 sind Char-Literale wie ' ' und #09 nicht mehr AnsiChars, sondern WideChars. Nun enthält ein Set für jeden möglichen Wert des darunterliegenden Typen ein Flag-Bit. TOrdinals benötigt also drei Bits, TSysCharSet 256 Bits = 32 Bytes. Ein WideChar-Set jedoch wären 65536 Bits = 8 KB groß, und da das in den meisten Fällen unerwünscht ist, konvertiert der Delphi-Compiler diese Sets unter besagter Warnung zu AnsiChar-Sets.
Stephan schrieb:
[DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString'
[...]
[DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string'
String[n] entspricht SmallString<n> und ist ein auf n AnsiChars begrenzter String. Die anderen Strings, die du benutzt, basieren nun aber auf WideChar, weshalb implizite Konvertierungen stattfinden.
Die URLDecode()-Funktion unterstützt allerdings Unicode-Codierungen nicht richtig; du könntest einfach die entsprechende Funktion aus Indy 10 ausleihen:
// IdURI.pas, l. 302ff: class function TIdURI.URLDecode(ASrc: string): string; var i: Integer; ESC: string; CharCode: Integer; begin Result := ''; {Do not Localize} // S.G. 27/11/2002: Spaces is NOT to be encoded as "+". // S.G. 27/11/2002: "+" is a field separator in query parameter, space is... // S.G. 27/11/2002: well, a space // ASrc := StringReplace(ASrc, '+', ' ', [rfReplaceAll]); {do not localize} i := 1; while i <= Length(ASrc) do begin if ASrc[i] <> '%' then begin {do not localize} Result := Result + ASrc[i]; // Copy the char Inc(i); // Then skip it end else begin Inc(i); // skip the % char if not CharIsInSet(ASrc, i, 'uU') then begin {do not localize} // simple ESC char ESC := Copy(ASrc, i, 2); // Copy the escape code Inc(i, 2); // Then skip it. try CharCode := IndyStrToInt('$' + ESC); {do not localize} Result := Result + Char(CharCode); except end; end else begin // unicode ESC code // RLebeau 5/10/2006: under Win32, the character will end // up as '?' in the Result when converted from Unicode to Ansi, // but at least the URL will be parsed properly ESC := Copy(ASrc, i+1, 4); // Copy the escape code Inc(i, 5); // Then skip it. try CharCode := IndyStrToInt('$' + ESC); {do not localize} Result := Result + {$IFDEF UNICODESTRING}Char{$ELSE}WideChar{$ENDIF}(CharCode); except end; end; end; end; end;