In Delphi Versions <= 2007, string was an alias for AnsiString (a single-byte character string type).
In Delphi Versions >= 2009, this changed, and string became an alias for UnicodeString (a multi-byte, UTF-16 character string type), while AnsiString remained available as a type for 8-bit character data.
This change was a major shift to include full Unicode support and has significant implications for code written in Delphi <= 2007 that is being migrated to Delphi 2009 or later.
Key Differences and Migration Implications
String Alias:- Delphi 2007 and earlier: String = AnsiString. The data was 8-bit and its interpretation (code page) was generally linked to the operating system's regional settings.
- Delphi 2009 and later: String = UnicodeString. The data is 16-bit (WideChar), typically using UTF-16 encoding, allowing for a broad range of characters.
- Delphi 2007: Char = AnsiChar (8-bit).
- Delphi 2009: Char = WideChar (16-bit).
Type | Delphi 2007 | Delphi 2009, XE -------+-------------+---------------- byte | byte | byte (no change) String | AnsiString | UnicodeString Char | AnsiChar | WideChar PChar | PAnsiChar | PWideChar
Data Handling:
- Direct assignments between AnsiString and the new UnicodeString (string) in Delphi 2009 involve implicit conversions, which can cause to performance issues or, more importantly, data loss if not handled carefully. The compiler will often issue warnings for these conversions.
- The internal structure of AnsiString itself changed slightly between versions (e.g., in Delphi 2009, it stores a code page number, which was not present in Delphi 2007's AnsiString), making sharing strings between DLLs compiled with different versions problematic.
Migration pieces of Advice
To migrate code that uses strings between these versions, you generally have preferred approaches:- Explicitly Ansi-fy the Code (Short-term fix): Replace all instances of the generic string, Char, and PChar with their explicit 8-bit equivalents: AnsiString, AnsiChar and PAnsiChar. This retains the old behavior but means your application will not leverage Unicode natively and will still encounter conversion overhead when interacting with the rest of the Unicode VCL/RTL in Delphi 2009.
- Resort to Unicode: Update your code to use the native UnicodeString (string) type throughout your application. Use AnsiString only at the boundaries where you interact with legacy data, files, or external APIs that require ANSI encoding (e.g., when saving or loading data from an older database). Use functions like
TEncoding.GetStringto properly decode data. - The correction isn’t simple recompilation, but to audit every PChar, every SizeOf(Char) assumption, and every place where raw bytes to a file or socket expecting ANSI.
// Delphi <= 2007 code — assumes 1 byte per char, breaks silently under Unicode procedure TrimBuffer(var Buf: array of Char; MaxLen: Integer); var P: PChar; begin P := @Buf[0]; Inc(P, MaxLen); // wrong stride Char is 2 bytes P^ := #0; end; -
Compiler directives and conditional code
The Version constants are not intuitive but they may lead to mistakes:
{$IFDEF VER150} // Delphi 7 {$IFDEF VER185} // Delphi 2007 Win32 has VER180 & VER185 {$IFDEF VER200} // Delphi 2009 Tiburon {$IFDEF VER210} // Delphi 2010 Weaver
Prefer to use Compiler Version than Version constants
...
If the codebase has already passed one migration, it likely has{$IFDEF}blocks keyed to old version constants. Don’t delete these blindly — audit each one with attention.
The ANSI function to Ansi-fy, syntax for string
| Ansi-fy | Wide Char, Unicode | Units | |
const
C = '...'; |
const
C: AnsiString = '...'; |
||
| CompareText | AnsiCompareText | SysUtils; AnsiStrings | |
| CompareStr | AnsiCompareStr | SysUtils; AnsiStrings | |
| FindWindow | FindWindowA | FindWindowW (in Delphi Versions >= 2009 the same as FindWindowW) |
|
| GetDiskFreeSpace | GetDiskFreeSpaceA | GetDiskFreeSpace (in Delphi Versions >= 2009 calls GetDiskFreeSpaceW) |
Windows |
| GetTempPath | GetTempPathA | GetTempPath (in Delphi Versions >= 2009 calls GetTempPathW) |
Windows |
| ShellExecute | ShellExecuteA | ShellExecuteW (in Delphi Versions >= 2009 the same as ShellExecute) |
ShellApi |
| ShellExecute | ShellExecuteA | ShellExecuteW (in Delphi Versions >= 2009 the same as ShellExecute) |
ShellApi |
| ShellExecuteInfo | ShellExecuteInfoA | ShellExecuteInfoW (in Delphi Versions >= 2009 the same as ShellExecuteInfo) |
|
| SHGetPathFromIDList | SHGetPathFromIDListA | SHGetPathFromIDList (in Delphi Versions >= 2009 calls SHGetPathFromIDListW) |
ShlObj |
| StrAlloc | AnsiStrAlloc | in Delphi Versions >= 2009 StrAlloc calls WideStrAlloc | SysUtils |
Delphi 2009 has got the unit
AnsiStrings.pas appeared in ..\source\Win32\rtl\common.This article will not be complete, some text was removed intentionally. If you are unable to apply this, please contact for paid consultation.
Данная статья не будет полной, часть текста была удалена намеренно. Если вам не удалось применить, обращайтесь за платной консультацией.

No comments:
Post a Comment