400 likes | 642 Views
64-bit and VCL Styles. Deep Dive. Delphi 64-bit. What’s the same?. Integer, Longint , Cardinal – still 32bits Int64, UInt64 – still 64bits UnicodeString , AnsiString , WideString Exceptions Runtime Library (RTL) SysUtils , Classes, etc…. Delphi 32 and 64-bit Type Sizes.
E N D
64-bit and VCL Styles Deep Dive
What’s the same? • Integer, Longint, Cardinal – still 32bits • Int64, UInt64 – still 64bits • UnicodeString, AnsiString, WideString • Exceptions • Runtime Library (RTL) • SysUtils, Classes, etc…
Delphi 32 and 64-bit Type Sizes Signed types Delphi/32 Delphi/64 ShortInt 1 byte SmallInt 2 bytes LongInt 4 bytes Integer 4 bytes Int64 8 bytes Unsigned types Delphi/32 Delphi/64 Byte 1 byte Word 2 bytes LongWord4 bytes Cardinal 4 bytes UInt64 8 bytes
What’s different? • NativeInt, NativeUint – 64bits • Pointer (all pointers) – 64bits • Dynamic Arrays – 64bit indexing • Floating point math - Double
Delphi 32 and 64-bit Type Sizes Signed types Delphi/32 Delphi/64 NativeInt4 bytes 8 bytes Unsigned types Delphi/32 Delphi/64 NativeUInt4 bytes8 bytes
Delphi 32 and 64-bit Pointer Types Pointer types Delphi/32 Delphi/64 Pointer String Class instance Class reference Interface AnsiString 4 bytes 8 bytes WideString UnicodeString Procedure pointer Dynamic array PAnsiChar PWideChar PChar
Instructions and Addresses • 64 bit address space • Limited by physical hardware • Same core Intel instruction set • New REX prefix for 64bit instructions • RIP-relative addressing • Jumps – relative +/- 2GB • 16 byte stack alignments • Online resources • http://msdn.microsoft.com/en-us/magazine/cc300794.aspx • http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Delphi 64-bit on Windows • Same Windows API • CreateWindowEx, PeekMessage, etc.. • Same Delphi RTL • SysUtils, Classes, Generics.Collections, etc… • Same VCL • Forms, Graphics, Controls, Menus, etc..
Pre-Defined Conditionals • Category Identifier dcc32 dcc64 • Compiler DCC defined definedVER230 defined defined • Platform MSWINDOWS defineddefinedWIN32 defined not definedWIN64 not defined defined • CPU CPU386 defined not definedCPUX86 defined not defined CPUX64 not defined defined • Availability ASSEMBLER defineddefinedUNICODE defined defined
Delphi 64-bit on Windows – some gotcha’s • SizeOf(Pointer) <> SizeOf(Integer) • Integer<->Pointer casts will break in 64bit • SizeOf(THandle) = SizeOf(Pointer) • All Handles = SizeOf(Pointer) (HWND, HDC, etc..). • All code in process must be 64bit • Must have 64bit versions of external non-Delphi libraries (DLLs) • One, and only one, calling convention • register, pascal, cdecl, stdcall are ignored. • safecall is still “special” • Old “pointer math” code may break • Works in 32 and 64bit: MyPtr := PByte(P) + 10; • TList’s internal FList is now a TPointerList. Used to be a PPointerList. Removing ^ should be sufficient to port from 32-bit to 64-bit. • Tag property is now a NativeInt (32-bit vs 64-bit)
Delphi 64-bit on Windows – some gotcha’s • Inline Assembly • Cannot mix asm blocks with Pascal code • Only procedural level asm blocks supported • Stack must be 16-byte aligned at each call instruction • Define locals for temp storage • Do not modify the RSP stack pointer • New unified calling convention. First 4 parameters in registers, RCX, RDX, R8, R9 (or XMM0-XMM3) • Exception unwinding • No change for pure Delphi code. Exceptions function identically. • Inline Assembly can cause exception unwinding to fail if not properly written. • SHL/SHR – 32-bit values (Integer et al) will only shift in 32-bit space. 64-bit values will of course shift in 64-bit space. • No Extended type in 64-bit. Use TExtendedRec80 if necessary (binary files with Extendeds in them for instance)
Windows API gotcha’s • SetWindowLong / GetWindowLong should be replaced by SetWindowLongPtr / GetWindowLongPtr for GWLP_HINSTANCE, GWLP_WNDPROC, etc… as they return pointers and handles. • Pointers passed to SetWindowLongPtr should be type-casted to LONG_PTR and not to Integer / Longint. • SetWindowLong mapped to SetWindowLongPtr in Windows.pas. • Calls to our declaration of SetWindowLong are safe, as long as they are cast correctly.
Windows API gotcha’s (con’t) • Use explicit casts to WPARAM and LPARAM where appropriate. • Example: Passing pointers through SendMessageSendMessage(hWnd, WM_SETTEXT, 0, LPARAM(@MyCharArray)); • Use LRESULT to cast message results • Example: Message.Result := LRESULT(Self); • Message cracker records (TWMxxx) changed • Alignment changes and field-size changes
What can I do today? • Find all Integer<->Pointer casts, including Integer<->instance casts. • Check for Pointer size assumptions • Ensure external dependencies are also 64bit • Image/bitmap libraries • Hardware interfaces libraries • ActiveX controls • Consider rewriting Assembler in pure-Pascal • Better future portability (think ARM CPUs…) • Rely more on algorithmic performance rather than raw assembly performance. • Make sure you know what bit-size (32 vs 64) you’re shifting with SHL/SHR.
What’s New in the VCL? • 64-bit • VCL Styles
Themes in Delphi/C++Builder XE and earlier • Only 1 "theme" supported (native Windows) • 3rd party products required to change look of VCL apps • Current “skinning" products for Windows common controls • Requiring hooking WndProc's • Intercepting control messages • Separate controls needed for "custom" controls • TCustomControl / TGraphicControl descendants
VCL Styles • Multiple styles provided/supported • Custom style file creation • Custom style classes • Pluggable style engine • Works with TWinControl and TGraphicControl descendants
VCL Styles • TThemeServices replaced by TCustomStyleServices • Extends TThemeServices with more parts, states and methods • TStyleEngine • Processes control messages • Calls StyleServices to render parts • TStyleManager • Provides services such as • LoadFromFile • LoadFromResource • RegisterStyle • RegisterStyleClass - Associates file extension with Style class • SetStyle • Style selection • Style engine selection • Providing custom styles • Create style file (using provided style building tool) • Implement TCustomStyleServices descendant and render parts directly
What can’t be styled? • TMainMenu/TPopupMenu (main menu bar is styled, but not the pop-up parts) • Ribbon controls • OS dialogs
Typical Usage RTL • Uses Vcl.Styles, Vcl.Themes; • TStyleManager.SetStyle(‘Ruby Red Graphite’);
What’s new in the RTL? • 64-bit for Windows!!! • MacOSX - No COM, No ActiveX. :) • Windows specifics has been mapped to MacOSX equivalents wherever possible • TOSVersion • Architecture (32/64-bit), Platform (Win/Mac), Major, minor OS version, Service Pack info • TFormatSettings • replaces global format setting variables (that don't exist on MacOSX) • TZipFile - cross platform Zip support • SymLinks in IOUtils and SysUtils file handling routines • class function TFile.CreateSymLink(const Link, Target: string): Boolean; • TLoginCredentialService • Extensible framework agnostic login credential services with support for callbacks (success, failure, etc) • TPoint, TRect, TSize - new methods and properties • TPointF, TRectF, TSizeF - floating point versions
TFormatSettings (SysUtils) type TFormatSettings = record // System.SysUtils … CurrencyString: string; CurrencyFormat: Byte; CurrencyDecimals: Byte; DateSeparator: Char; TimeSeparator: Char; ListSeparator: Char; ShortDateFormat: string; LongDateFormat: string; TimeAMString: string; TimePMString: string; ShortTimeFormat: string; LongTimeFormat: string; ShortMonthNames: array[1..12] of string; LongMonthNames: array[1..12] of string; ShortDayNames: array[1..7] of string; LongDayNames: array[1..7] of string; ThousandSeparator: Char; DecimalSeparator: Char; TwoDigitYearCenturyWindow: Word; … end;
TZipFile (System.Zip) type TZipFile = class .. public … procedure Open(ZipFileName: string; OpenMode: TZipMode); overload; procedure Open(ZipFileStream: TStream; OpenMode: TZipMode); overload; procedure Close; procedure Extract(FileName: string; Path: string = ''; CreateSubdirs: Boolean=True); overload; procedure Extract(Index: Integer; Path: string = ''; CreateSubdirs: Boolean=True); overload; procedure ExtractAll(Path: string = ''); procedure Read(Index: Integer; out Bytes: TBytes); overload; procedure Read(FileName: string; out Stream: TStream); overload; procedure Read(Index: Integer; out Stream: TStream); overload; procedure Add(FileName: string; ArchiveFileName: string = ''; Compression: TZipCompression = zcDeflate); overload; … property FileCount: Integer read GetFileCount; property FileNames: TArray<string> read GetFileNames; … end;
TLoginCredentialService type TLoginCredentialService = class sealed public const Default = ''; DefaultUsrPw = 'DefaultUsrPw'; // do not localize DefaultUsrPwDm = 'DefaultUsrPwDm'; //do not localize … strict private class var FLoginHandlers: TStringList; strict private class constructor Create; class destructor Destroy; class function IndexOfHandler(const Context: TLoginCredentialEvent): Integer; public class procedure RegisterLoginHandler(const Context: string; const HandlerEvent: TLoginCredentialEvent); static; class procedure UnregisterLoginHandler(const Context: string; const HandlerEvent: TLoginCredentialEvent); static; class function GetLoginCredentialEvent(const Context: string): TLoginCredentialEvent; static; class function GetLoginCredentials(const Context: string; Sender: TObject; const Callback: TLoginEvent): Boolean; overload; static; class function GetLoginCredentials(const Context: string; const Callback: TLoginFunc): Boolean; overload; static; class function GetLoginCredentials(const Context: string; var Username, Password: string): Boolean; overload; static; class function GetLoginCredentials(const Context: string; var Username, Password, Domain: string): Boolean; overload; static; end;
TPointF (System.Types) type TPointF = record X: Single; Y: Single; public constructor Create(const P: TPointF); overload; constructor Create(const X, Y: Single); overload; constructor Create(P: TPoint); overload; class operator Equal(const Lhs, Rhs: TPointF): Boolean; class operator NotEqual(const Lhs, Rhs: TPointF): Boolean; class operator Add(const Lhs, Rhs: TPointF): TPointF; class operator Subtract(const Lhs, Rhs: TPointF): TPointF; function Distance(const P2: TPointF): Double; procedure SetLocation(const X, Y: Single); overload; procedure SetLocation(const P: TPointF); overload; procedure SetLocation(const P: TPoint); overload; … function Add(const Point: TPointF): TPointF; overload; function Add(const Point: TPoint): TPointF; overload; function Subtract(const Point: TPointF): TPointF; overload; function Subtract(const Point: TPoint): TPointF; overload; function IsZero: Boolean; function Ceiling: TPoint; function Truncate: TPoint; function Round: TPoint; end;
What’s New in C++? • FireMonkey • Live Bindings • DataSnap • Extended RTTI • Audits and Metrics
Demos • 32-bit/64-bit Stylish Fish Facts • C++ Stylish Fish Facts • Stylish Live Bindings Fish Facts