32 ビット Delphi アプリケーションの 64 ビット Windows への変換
64 ビット Windows アプリケーション開発 への移動
64 ビット Windows 版に変換する 32 ビット Windows Delphi アプリケーションのコード ベースがある場合は、以下の作業が必要です。
- 対象となる 32 ビット アプリケーションを IDE で開き、64 ビット Windows ターゲット プラットフォームを追加してアクティブにし、アプリケーションを 64 ビット Windows アプリケーションとしてコンパイルする (詳細については、「マルチデバイス アプリケーション作成のステップ」を参照)。
- 以下の問題(大半はポインタ操作、NativeInt サイズ、アセンブリ コードに関連するもの)を見直し対処する。
目次
ポインタ操作
使用しているコード ベースでのポインタ操作を見直す必要があります。
- すべてのポインタのサイズは次のとおり変更されています。
- 32 ビット Windows プラットフォームでは、ポインタは 4 バイトです。
- 64 ビット Windows プラットフォームでは、ポインタは 8 バイトです。
- 次のようには想定できません。
SizeOf(Pointer)=SizeOf(Integer/Cardinal/Longint)
- ポインタをインクリメントする場合、64 ビット ポインタの処理は、32 ビット ポインタの処理と同じではないことがあることに注意してください。 必要に応じてコードで調整します。
- 正しい:
MyPtr := PByte(P) + 10;
- 下位互換性を維持する場合:
MyPtr := PAnsiChar(P) + 10;
- 正しくない:
MyPtr := Pointer(Integer(P) + 10);
- 次のようには想定できません。
SizeOf(Pointer) == 4
- 正しい:
Move(FSelection[Index + 1], FSelection[Index], (FSelectionCount - Index - 1) * SizeOf(Pointer));
- 正しくない:
Move(FSelection[Index + 1], FSelection[Index], (FSelectionCount - Index - 1) * 4);
64 ビット Windows アプリケーションでのポインタの使用について詳細は、MSDN の記事「ポインタの使用規則」を参照してください。
整数型
- 64 ビット Windows プラットフォームでは、整数は 4 バイトのままです。
NativeInt
のサイズは変わります
- 64 ビット Windows プラットフォームでは、
NativeInt
のサイズは 8 バイトになりました。 - 32 ビット Windows プラットフォームでは、
NativeInt
のサイズは 4 バイトのままです。
インライン アセンブリ コード
ユーザーのアプリケーションにインライン アセンブリ(ASM)コードが含まれる場合は、ASM コードを調べて、次のとおりに変更する必要があります。
- アセンブリ言語文と Pascal コードが混在していると、64 ビット アプリケーションではサポートされません。 アセンブリ言語文を Pascal コードまたはアセンブリ コードで完全に記述された関数に置き換えます。
- IA-32 から Intel 64 へのアセンブリ コードへの移植は、単にコードをコピーするだけでは実現できません。 ポインタのサイズやアラインメントなどのアーキテクチャ仕様を考慮します。 新しい命令群についてプロセッサのマニュアルを参照すると便利です。 異なるアーキテクチャに対して同じコードをコンパイルする場合は、条件定義を使用します。 「インライン アセンブリ コードの使用」の「クロスプラットフォーム コードでの条件定義の使用」を参照してください。
RAD Studio でサポートするのは、Intel x86 SSE4.2 および AMD 3dNow!、x64 では、Intel/AMD SSE4.2 です。
詳細については、以下を参照してください:
Winapi 問題
- ポインタを
SendMessage/PostMessage/TControl.Perform
に渡すとき、wParam
とlParam
パラメータはInteger/Longint
ではなく、WPARAM/LPARAM
型に型キャストする必要があります。- 正しい:
SendMessage(hWnd, WM_SETTEXT, 0, LPARAM(@MyCharArray));
- 正しくない:
SendMessage(hWnd, WM_SETTEXT, 0, Integer(@MyCharArray));
- 正しい:
- ポインタやハンドルを返すときに、
GWLP_HINSTANCE
、GWLP_ID
、GWLP_USERDATA
、GWLP_HWNDPARENT
およびGWLP_WNDPROC
に対して、SetWindowLong/GetWindowLog
をSetWindowLongPtr/GetWindowLongPtr
に置き換えます。SetWindowLongPtr
に渡されるポインタは、Integer/Longint
ではなくLONG_PTR
に型キャストする必要があります。- 正しい:
SetWindowLongPtr(hWnd, GWLP_WNDPROC, LONG_PTR(@MyWindowProc));
- 正しくない:
SetWindowLong(hWnd, GWL_WNDPROC, Longint(@MyWindowProc));
- 正しい:
TMessage.Result
フィールドに割り当てられるポインタは、Integer/Longint
ではなくLRESULT
に型キャストを使用する必要があります。- 正しい:
Message.Result := LRESULT(Self);
- 正しくない:
Message.Result := Integer(Self);
- 正しい:
- Windows メッセージ ハンドラに対して、すべての
TWM...
レコードは、各フィールドに対して、正しい Windows 型を使用する必要があります。Msg: UINT; wParam: WPARAM; lParam: LPARAM; Result: LRESULT)
レコード型のデータ フィールドのアラインメント
Delphi のこれまでのバージョンでは、外部ライブラリ、特に、レコード型または構造体型のパラメータが必要な特定の外部 Windows API 関数を呼び出すときに適切なデータ アラインメントを確保するために、パック レコード("packed record")が使用されていました。 "パディング" を行い、必要なデータ フィールドを必要に応じて揃えるために、使用されないデータ フィールドが導入されていました。 現在のコンパイラ実装では、ほとんどの場合、パック レコードをこのように使用する必要はありません。 既存のソース コードを見直して、不要なパック レコードを通常のレコードに変更します。"パディング" は、わかりやすく保守しやすいソース コードにするために使用されます。
既存のデータ ファイルと Delphi の旧バージョンとの互換性を保つ必要がある場合は、以前のレコード構造がまだ必要なソース コードにコンパイラ指令 {$OLDTYPELAYOUT ON} を適用します。
解決が必要なその他の問題(重要度小
- VCL-RTL の DataEvent プロシージャは、
NativeInt
のサイズが変わると影響があります。
- 仮想メソッドでコンパイラ オーバーライド エラーが発生することがあります(E2170 非仮想メソッドはオーバーライドできません)。 この場合、コードの変更が必要です。
- 実行時関数パッチ(関数をリダイレクトする無条件ジャンプの挿入など)は、64 ビット命令で書き換える必要があります。
- 64 ビット外部 .obj ファイル: ユーザーの 64 ビット Windows アプリケーションを外部 .obj ファイルにリンクする場合は、64 ビット Windows アプリケーションにリンクする、64 ビット版の .obj ファイルが必要です。