Konvertieren von 32-Bit-Delphi-Anwendungen in 64-Bit-Windows
Nach oben zu 64-Bit-Windows-Anwendungsentwicklung
Wenn Sie eine Codebasis mit 32-Bit-Windows-Delphi-Anwendungen nach 64-Bit-Windows konvertieren möchten, sollten Sie
- Die 32-Bit-Anwendung in der IDE öffnen, die 64-Bit-Windows-Zielplattform hinzufügen und die Anwendung als 64-Bit-Windows-Anwendung compilieren. (Einzelheiten dazu finden Sie unter Schritte bei der Entwicklung von geräteübergreifenden Anwendungen.)
- Die folgenden Punkte überprüfen und ggf. anpassen (beziehen sich hauptsächlich auf Zeigeroperationen, NativeInt-Größe und Assembly-Code).
Inhaltsverzeichnis
Zeigeroperationen
Sie sollten Zeigeroperationen in Ihrer Codebasis überprüfen.
- Die Größer aller Zeiger wurde folgendermaßen geändert:
- Auf einer 32-Bit-Windows-Plattform ist ein Zeiger 4 Byte groß.
- Auf einer 64-Bit-Windows-Plattform ist ein Zeiger 8 Byte groß.
- Sie können von Folgendem ausgehen:
SizeOf(Pointer)=SizeOf(Integer/Cardinal/Longint)
- Beachten Sie beim Inkrementieren von Zeigern, dass das Verhalten eines 64-Bit-Zeigers nicht identisch mit dem eines 32-Bit-Zeigers sein kann. Sie müssen ggf. Anpassungen in Ihrem Code vornehmen.
- Richtig:
MyPtr := PByte(P) + 10;
- Abwärtskompatibel:
MyPtr := PAnsiChar(P) + 10;
- Falsch:
MyPtr := Pointer(Integer(P) + 10);
- Sie können von Folgendem ausgehen:
SizeOf(Pointer) == 4
- Richtig:
Move(FSelection[Index + 1], FSelection[Index], (FSelectionCount - Index - 1) * SizeOf(Pointer));
- Falsch:
Move(FSelection[Index + 1], FSelection[Index], (FSelectionCount - Index - 1) * 4);
Weitere Informationen über die Verwendung von Zeigern in 64-Bit-Windows-Anwendungen finden Sie in dem MSDN-Artikel Rules for Using Pointers.
Integer-Typen
- Auf einer 64-Bit-Windows-Plattform bleiben Integerwerte 4 Byte groß.
Die Größe von NativeInt
ändert sich
- Auf der 64-Bit-Windows-Plattform beträgt die Größe von
NativeInt
jetzt 8 Byte. - Auf der 32-Bit-Windows-Plattform beträgt die Größe von
NativeInt
weiterhin 4 Byte.
Inline-Assembly-Code
Wenn Ihre Anwendung ASM-Code (Inline Assembly) enthält, müssen Sie den ASM-Code überprüfen und die folgenden Änderungen vornehmen:
- In 64-Bit-Anwendungen wird das Mischen von Assembly-Anweisungen mit Pascal-Code nicht unterstützt. Ersetzen Sie Assembly-Anweisungen entweder durch Pascal-Code oder durch vollständig in Assembly geschriebene Funktionen.
- Das Portieren von IA-32 nach Intel 64 kann nicht einfach durch Kopieren des Codes erfolgen. Bedenken Sie die Architektur-Spezifika, wie etwa die Größe von Zeigern und die Ausrichtung. Suchen Sie ggf. im Prozessor-Handbuch nach neuen Anweisungen. Verwenden Sie zum Compilieren desselben Codes für unterschiedliche Architekturen konditionale Definitionen. Siehe Verwenden von konditionalen Definitionen für plattformübergreifenden Code in "Verwendung des integrierten Assemblers".
RAD Studio unterstützt Intel x86 über SSE4.2 und AMD 3dNow und bei x64 Intel/AMD über SSE4.2.
Weitere Informationen finden Sie unter:
- 64-Bit-Inline-Assembler von Delphi
- Verwendung des integrierten Assemblers
- Assembler-Prozeduren und -Funktionen
WinAPI-Aspekte
- Wenn Sie Zeiger an
SendMessage/PostMessage/TControl.Perform
übergeben, sollten die ParameterwParam
undlParam
in den TypWPARAM/LPARAM
und nicht inInteger/Longint
umgewandelt werden.- Richtig:
SendMessage(hWnd, WM_SETTEXT, 0, LPARAM(@MyCharArray));
- Falsch:
SendMessage(hWnd, WM_SETTEXT, 0, Integer(@MyCharArray));
- Richtig:
- Ersetzen Sie
SetWindowLong/GetWindowLog
durchSetWindowLongPtr/GetWindowLongPtr
fürGWLP_HINSTANCE
,GWLP_ID
,GWLP_USERDATA
,GWLP_HWNDPARENT
undGWLP_WNDPROC
, da sie Zeiger und Handles zurückgeben. Zeiger, die anSetWindowLongPtr
übergeben werden, sollten in den TypLONG_PTR
und nicht inInteger/Longint
umgewandelt werden.- Richtig:
SetWindowLongPtr(hWnd, GWLP_WNDPROC, LONG_PTR(@MyWindowProc));
- Falsch:
SetWindowLong(hWnd, GWL_WNDPROC, Longint(@MyWindowProc));
- Richtig:
- Zeiger, die dem Feld
TMessage.Result
zugewiesen werden, sollten in den TypLRESULT
anstatt inInteger/Longint
umgewandelt werden.- Richtig:
Message.Result := LRESULT(Self);
- Falsch:
Message.Result := Integer(Self);
- Richtig:
- Alle
TWM...
-Records für die Behandlungsroutinen von Fensterbotschaften müssen die korrekten Windows-Typen für die Felder verwenden:Msg: UINT; wParam: WPARAM; lParam: LPARAM; Result: LRESULT)
Datenfeldausrichtung bei Record-Typen
In früheren Versionen von Delphi wurde die korrekte Datenausrichtung beim Aufruf von externen Bibliotheken und insbesondere von bestimmten externen Windows-API-Funktionen, für die record- oder struct-Parameter erforderlich waren, mit packed record sichergestellt. Nicht verwendete Datenfelder wurden "aufgefüllt", damit die erforderlichen Datenfelder wie benötigt ausgerichtet werden konnten. Die aktuelle Compiler-Implementierung macht eine derartige Verwendung von packed Records in den meisten Fällen überflüssig. Durch Überarbeitung von vorhandenem Quellcode und Entfernung von nutzlosen packed Records und "Auffüllungen" wird der Quellcode klarer und einfacher zu warten.
Wenn Ihre vorhandenen Datendateien kompatibel mit älteren Versionen von Delphi bleiben sollen, geben Sie die Compiler-Direktive {$OLDTYPELAYOUT ON} für Quellcode an, dessen alte Record-Organisation weiterhin benötigt wird.
Sonstige zu beachtende Aspekte
- Die Prozedur DataEvent in der VCL-RTL ist von der Größenänderung von
NativeInt
betroffen.
- Es wird evtl. ein Compiler-Fehler für virtuelle Methoden bezüglich des Überschreibens ausgegeben (E2170: Eine nicht-virtuelle Methode kann nicht überschrieben werden). In diesem Fall sind Codeänderungen erforderlich.
- Das Funktions-Patching zur Laufzeit, wie z.B. das Einfügen einer nicht bedingten Sprunganweisung zur Umleitung einer Funktion, muss als 64-Bit-Anweisung umgeschrieben werden.
- Externe 64-Bit-Objektdateien: Wenn Sie Ihre 64-Bit-Windows-Anwendung mit einer externen Objektdatei (.obj) linken möchten, benötigen Sie eine 64-Bit-Version der .obj-Datei zum Linken mit einer 64-Bit-Windows-Anwendung.