32 ビット Delphi アプリケーションの 64 ビット Windows への変換
出典: RAD Studio XE2
Windows 向けの 64 ビット クロスプラットフォーム アプリケーション開発 への移動
64 ビット版に変換する 32 ビット Delphi アプリケーションのコード ベースがある場合は、以下の作業が必要です。
- 対象となる 32 ビット アプリケーションを IDE で開き、64 ビット ターゲット プラットフォームを追加してアクティブにし、アプリケーションを 64 ビット アプリケーションとしてコンパイルする (詳細については、「クロスプラットフォーム アプリケーション作成のステップ」を参照してください)。
- 以下の問題(大半はポインタ操作、NativeInt サイズ、アセンブリ コードに関連するもの)を見直し対処する。
目次 |
ポインタ操作
使用しているコード ベースでのポインタ操作を見直す必要があります。
- すべてのポインタのサイズは次のとおり変更されています。
- 32 ビット プラットフォームでは、ポインタは 4 バイトです。
- 64 ビット プラットフォームでは、ポインタは 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 ビット プラットフォームでは、整数は 4 バイトのままです。
NativeInt のサイズは変わります
- 64 ビット プラットフォームでは、
NativeIntのサイズは 8 バイトになりました。 - 32 ビット プラットフォームでは、
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 ビット アプリケーションを外部 .obj ファイルにリンクする場合は、64 ビット アプリケーションにリンクする、64 ビット版の .obj ファイルが必要です。