古いVisual Studioで作成したMFCプロジェクトを変換して64ビットアプリケーションをビルドした場合のエラーを回避する話。
x64ビルド環境
Microsoftの統合開発環境(IDE)「Visual Studio」は32ビットで動作しています。ビルド時にコンパイラーを選択することで、様々なアーキテクチャー向けのプログラムを紡ぎだすように設計されています。
そのため、x64アプリを作成するためには、「Visual Studio」セットアップ時に、64ビットのビルドツールを追加でセットアップしておく必要があります。(すべてインストールを選んでおけば間違いない)
互換性
プロジェクトは新しいIDEに移行する際に変換が行われます。変換と言っても、プロジェクト内のファイル配置や、ファイルの互換性など、プロジェクトを開いた際の変換をしてくれているだけで、実際にビルド操作を行うと、多くのエラーが出力される。
プロジェクトに「スタティックライブラリ」などがリンクされている場合には、64ビット用の「スタティックライブラリ」にリンクするように設定しておかないと、ビルド時にエラーになってしまう。
互換性や移行のウィザードは表面的なもので、実際にコード内やビルド時の考慮などは含まれていないことが多い。
x64プラットフォーム構成の作成
次の手順で、64ビット向けのプラットフォーム構成を追加します。
- [プロジェクト|プロパティ]メニューを選択してプロジェクトのプロパティを表示する。
- [構成マネージャ]ボタンを選択する。
- 表示された[構成マネージャ]画面の[アクティブ ソリューション プラットフォーム]リストから[新規作成]を選択する。
- 表示された[新しいソリューション プラットフォーム]画面で[新しいプラットフォームを入力または選択してください]リストから[x64]を選択する。
- [OK]ボタンを選択する。
- プラットフォームに[x64]が追加されアクティブになります。
- Win32用の設定がとりあえずコピーされているので、構成を64ビット用に修正します。
- ビルドを行う。(ビルドエラーが延々と出力されます)
ビルドメッセージと回避方法
1>C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(431) : error C2146: 構文エラー : ‘;’ が、識別子 ‘rgclsidAllowed’ の前に必要です。
1>C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(431) : error C4430: 型指定子がありません – int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(431) : error C4430: 型指定子がありません – int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(6041) : error C2039: ‘rgclsidAllowed’ : ‘ATL::ATL_PROPMAP_ENTRY’ のメンバではありません。
1> C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(422) : ‘ATL::ATL_PROPMAP_ENTRY’ の宣言を確認してください。
1>C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcom.h(6041) : error C2660: ‘ATL::CComVariant::ReadFromStream’ : 関数に 4 個の引数を指定できません。
上記のようなメッセージであれば、マイクロソフト セキュリティ情報 MS09-035(Visual Studio の Active Template Library の脆弱性により、リモートでコードが実行される [KB969706])が適用されていない可能性があるので、修正パッチを適用する。 WindowsUpdateでは更新されない。
1>ライブラリ x64\Debug/*****.lib とオブジェクト x64\Debug/*****.exp を作成中
1>*****.exp : error LNK2001: 外部シンボル “_DllCanUnloadNow@0” は未解決です。
1>*****.exp : error LNK2001: 外部シンボル “_DllGetClassObject@12” は未解決です。
1>*****.exp : error LNK2001: 外部シンボル “_DllRegisterServer@0” は未解決です。
1>*****.exp : error LNK2001: 外部シンボル “_DllUnregisterServer@0” は未解決です。
1>x64\Debug/*****.dll : fatal error LNK1120: 外部参照 4 が未解決です。
プロジェクト内の下記の部分を探して
#pragma comment(linker, "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow@0,PRIVATE") #pragma comment(linker, "/EXPORT:DllGetClassObject=_DllGetClassObject@12,PRIVATE") #pragma comment(linker, "/EXPORT:DllRegisterServer=_DllRegisterServer@0,PRIVATE") #pragma comment(linker, "/EXPORT:DllUnregisterServer=_DllUnregisterServer@0,PRIVATE")
次のように書き換える
#ifdef _WIN64 #pragma comment(linker, "/EXPORT:DllCanUnloadNow=DllCanUnloadNow,PRIVATE") #pragma comment(linker, "/EXPORT:DllGetClassObject=DllGetClassObject,PRIVATE") #pragma comment(linker, "/EXPORT:DllRegisterServer=DllRegisterServer,PRIVATE") #pragma comment(linker, "/EXPORT:DllUnregisterServer=DllUnregisterServer,PRIVATE") #else #pragma comment(linker, "/EXPORT:DllCanUnloadNow=_DllCanUnloadNow@0,PRIVATE") #pragma comment(linker, "/EXPORT:DllGetClassObject=_DllGetClassObject@12,PRIVATE") #pragma comment(linker, "/EXPORT:DllRegisterServer=_DllRegisterServer@0,PRIVATE") #pragma comment(linker, "/EXPORT:DllUnregisterServer=_DllUnregisterServer@0,PRIVATE") #endif
1>.\*****.cpp(46) : error C2440: ‘static_cast’ : ‘void (__cdecl C*****::* )(UINT)’ から ‘void (__cdecl CWnd::* )(UINT_PTR)’ に変換できません。
1>base から derived へのキャストには、dynamic_cast または static_cast が必要です。ON_WM_TIMER() で定義している関するの引数が変更されているため ヘッダーファイルのOnTimer (UINT idEvent)を探してOnTimer (UINT_PTR idEvent) にソースファイルのafx_msg void OnTimer(UINT nIDEvent)を afx_msg void OnTimer(UINT_PTR nIDEvent)に修正する。この他にもON_WM_NCHITTEST()の戻り値が、UINTからLRESULTに変更されたりしている。
.manifestファイルを適用している場合には、processorArchitecture=”x86″としていると、ビルドは成功しても実行時に、comdlgを呼び出すときに、どっちが呼び出されるは分からないので、processorArchitecture=”*”とする。
この修正作業で、x64プラットフォーム用のアプリを生成時に出力されるエラーメッセージが無くなるはずです。
スポンサーリンク
最後までご覧いただきありがとうございます。