RAD Studio XE2 is the major breakthrough in the line of all Delphi versions of this product. It allows deploying your applications both on Windows and Mac OS platforms. Additionally, it is now possible to create 64-bit Windows applications to fully benefit from the power of new hardware. Moreover, you can create visually spectacular applications with the help of the FireMonkey GPU application platform.
Its main features are the following:
64-bit platform support implies several important changes that each developer must keep in mind prior to the development of a new application or the modernization of an old one.
General
RAD Studio XE2 IDE is a 32-bit application. It means that it cannot load 64-bit packages at design-time. So, all design-time packages in RAD Studio XE2 IDE are 32-bit.
Therefore, if you develop your own components, you should remember that for the purpose of developing components with the 64-bit platform support, you have to compile run-time packages both for the 32- and 64-bit platforms, while design-time packages need to be compiled only for the 32-bit platform. This might be a source of difficulties if your package is simultaneously both a run-time and a design-time package, as it is more than likely that this package won't be compiled for the 64-bit platform. In this case, you will have to separate your package into two packages, one of which will be used as run-time only, and the other as design-time only.
For the same reason, if your design-time packages require that certain DLLs be loaded, you should remember that design-time packages can be only 32-bit and that is why they can load only 32-bit versions of these DLLs, while at run-time 64-bit versions of the DLLs will be loaded. Correspondingly, if there are only 64-bit versions of the DLL on your computer, you won't be able to use all functions at design-time and, vice versa, if you have only 32-bit versions of the DLLs, your application won't be able to work at run-time.
Extended type
For this type in a 64-bit applications compiler generates SSE2 instructions instead of FPU, and that greatly improves performance in applications that use this type a lot (where data accuracy is needed). For this purpose, the size and precision of Extended type is reduced:
TYPE | 32-bit | 64-bit |
---|---|---|
Extended | 10 bytes | 8 bytes |
The following two additional types are introduced to ensure compatibility in the process of developing 32- and 64-bit applications:
Extended80 – whose size in 32-bit application is 10 bytes; however, this type provides the same precision as its 8-byte equivalent in 64-bit applications.
Extended80Rec – can be used to perform low-level operations on an extended precision floating-point value. For example, the sign, the exponent, and the mantissa can be changed separately. It enables you to perform memory-related operations with 10-bit floating-point variables, but not extended-precision arithmetic operations.
Pointer and Integers
The major difference between 32- and 64-bit platforms is the volume of the used memory and, correspondingly, the size of the pointer that is used to address large memory volumes.
TYPE | 32-bit | 64-bit |
---|---|---|
Pointer | 4 bytes | 8 bytes |
At the same time, the size of the Integer type remains the same for both platforms:
TYPE | 32-bit | 64-bit |
---|---|---|
Integer | 4 bytes | 4 bytes |
That is why, the following code will work incorrectly on the 64-bit platform:
Ptr := Pointer(Integer(Ptr) + Offset);
While this code will correctly on the 64-bit platform and incorrectly on the 32-bit platform:
Ptr := Pointer(Int64(Ptr) + Offset);
For this purpose, the following platform-dependent integer type is introduced:
TYPE | 32-bit | 64-bit |
---|---|---|
NativeInt | 4 bytes | 8 bytes |
NativeUInt | 4 bytes | 8 bytes |
This type helps ensure that pointers work correctly both for the 32- and 64-bit platforms:
Ptr := Pointer(NativeInt(Ptr) + Offset);
However, you need to be extra-careful when developing applications for several versions of Delphi, in which case you should remember that in the previous versions of Delphi the NativeInt type had different sizes:
TYPE | Delphi Version | Size |
---|---|---|
NativeInt | D5 | N/A |
NativeInt | D6 | N/A |
NativeInt | D7 | 8 bytes |
NativeInt | D2005 | 8 bytes |
NativeInt | D2006 | 8 bytes |
NativeInt | D2007 | 8 bytes |
NativeInt | D2009 | 4 bytes |
NativeInt | D2010 | 4 bytes |
NativeInt | Delphi XE | 4 bytes |
NativeInt | Delphi XE2 | 4 or 8 bytes |
Out parameters
Some WinAPIs have OUT parameters of the SIZE_T type, which is equivalent to NativeInt in Delphi XE2. The problem is that if you are developing only a 32-bit application, you won't be able to pass Integer to OUT, while in a 64-bit application, you will not be able to pass Int64; in both cases you will have to pass NativeInt.
For example:
procedure MyProc(out Value: NativeInt);
begin
Value := 12345;
end;
var
Value1: NativeInt;
{$IFDEF WIN32}
Value2: Integer;
{$ENDIF}
{$IFDEF WIN64}
Value2: Int64;
{$ENDIF}
begin
MyProc(Value1); // will be compiled;
MyProc(Value2); // will not be compiled !!!
end;
Win API
If you pass pointers to SendMessage/PostMessage/TControl.Perform, the wParam and lParam parameters should be type-casted to the WPARAM/LPARAM type and not to Integer/Longint.
Correct:
SendMessage(hWnd, WM_SETTEXT, 0, LPARAM(@MyCharArray));
Wrong:
SendMessage(hWnd, WM_SETTEXT, 0, Integer(@MyCharArray));
Replace SetWindowLong/GetWindowLog with SetWindowLongPtr/GetWindowLongPtr for GWLP_HINSTANCE, GWLP_ID, GWLP_USERDATA, GWLP_HWNDPARENT and GWLP_WNDPROC as they return pointers and handles. Pointers that are passed to SetWindowLongPtr should be type-casted to LONG_PTR and not to Integer/Longint.
Correct:
SetWindowLongPtr(hWnd, GWLP_WNDPROC, LONG_PTR(@MyWindowProc));
Wrong:
SetWindowLong(hWnd, GWL_WNDPROC, Longint(@MyWindowProc));
Pointers that are assigned to the TMessage.Result field should use a type-cast to LRESULT instead of Integer/Longint.
Correct:
Message.Result := LRESULT(Self);
Wrong:
Message.Result := Integer(Self);
All TWM...-records for the windows message handlers must use the correct Windows types for the fields:
Msg: UINT; wParam: WPARAM; lParam: LPARAM; Result: LRESULT)
Assembler
In order to make your application (that uses assembly code) work, you will have to make several changes to it:
You can use conditional defines to make your application work with different architectures.
You can learn more about Assembly code here: http://docwiki.embarcadero.com/RADStudio/en/Using_Inline_Assembly_Code You can also look at the following article that will help you to make your application support the 64-bit platform: http://docwiki.embarcadero.com/RADStudio/en/Converting_32-bit_Delphi_Applications_to_64-bit_Windows
Exception handling
The biggest difference in exception handling between Delphi 32 and 64-bit is that in Delphi XE2 64-bit you will gain more performance because of different internal exception mechanism. For 32-bit applications, the Delphi compiler (dcc32.exe) generates additional code that is executed any way and that causes performance loss. The 64-bit compiler (dcc64.exe) doesn't generate such code, it generates metadata and stores it in the PDATA section of an executable file instead.
But in Delphi XE2 64-bit it's impossible to have more than 16 levels of nested exceptions. Having more than 16 levels of nested exceptions will cause a Run Time error.
Debugging
Debugging of 64-bit applications in RAD Studio XE2 is remote. It is caused by the same reason: RAD Studio XE2 IDE is a 32 application, but your application is 64-bit. If you are trying to debug your application and you cannot do it, you should check that the Include remote debug symbols project option is enabled.
To enable it, perform the following steps:
After that, you can run and debug your 64-bit application.
To enable remote debugging, perform the following steps:
After that, you can test the connection by clicking the Test Connection button. If your connection failed, check that your firewalls on both remote and local computers do not block your connection, and try to establish a connection once more. If your connection succeeded, click the Next button and then the Finish button. Select your newly created profile and click OK.
After performing these steps you will be able to debug your application on a remote computer. You application will be executed on a remote computer, but you will be able to debug it on your local computer with RAD Studio XE2.
For more information about working with Platform Assistant Server, please refer to http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Running_the_Platform_Assistant_on_Windows