本コンテンツは、2010年11月14日の日記からの転載に加筆したものとなります。
2015年7月20日現在では、個人開発者やオープンソース開発者、中小規模の企業・団体、学習、学術調査目的の開発者は無料で使えるVisual Studio Communityが登場しましたのでVisual C++/Studio Expressを使う必要があるのはVisual C++/Studio 2005~2012 Expressを使う場合と中小規模に該当しない企業がVisual Studioの分の経費節減を図る場合となります。
(2015/07/20追記)
Visual Studio 2010では比較的安価なStandard版がなくなり、最低でもProfessional版からとなったので、入手の難易度が金銭的に高まったといえる。
今後、MFC/ATL、リソースエディタが付いたVisual Studioを比較的安価に入手できるかどうかは分からないので、MFC/ATLを使わないことを前提にVisual C++ Expressにダウングレードするという選択を採るケースも増えるのではないだろうか。
また、MFC自体が今後どれだけメンテナンスされるかが分かりにくかったり、自分のプログラムに問題はないがMFCのセキュリティホールの修正で不具合が発生するリスクを考えるとMFCへの依存を減らしたほうが良いというケースも考えられる。
(事実、2011年4月のセキュリティ修正ではMS11-025を入れたVisual Studio 2008でMFCをスタティックリンクしたプログラムをコンパイルするとWindows 2000で起動しないプログラムができるという事象が発生している。)
そこで、本文は、Visual Studio上のVisual C++で作成したプログラムをVisual C++ 2010 Expressでコンパイルできるようにしたときの手順の記録を通して、Visual Studioで作ったプログラムをVisual C++ Expressなどに移植する手順を述べる。
Visual Studioで作ったプログラムをVisual C++ Expressに移植するにはある程度の手順を踏む必要がある。手順としては以下のようになるであろう。
当たり前ではあるが、プログラムをMFC/ATLに依存しないようにする必要がある。
プログラムをMFC/ATLに依存しないようにするに当たって、まずはVisual Studioの環境でできる限りMFC/ATLに依存しないアプリケーションロジックとユーザーインタフェースの分離を行うべきである。
アプリケーションロジックとユーザーインタフェースの分離を行って、動作を確認しておけばユーザーインタフェース部分のみを移植すればよくなるので、作業にかかる時間を短縮できるとともに不具合が発生する可能性も減らせるだろう。
アプリケーションロジックとユーザーインタフェースを分離したら、MFC/ATLに依存する部分をMFC/ATLに依存しないように書き換える。
MFC/ATLに依存する部分をMFC/ATLに依存しないように書き換えるにはいくつかの手が考えられる。
Win32 APIを直接使うのが面倒とか、これを機にクロスプラットフォームに対応したいといった向きにはウィジェット・ツールキットを使うことが考えられる。
ウィジェット・ツールキット(Wikipedia)などが参考になるだろう。
これらのツールキットにはオープンソースのものも結構あるので、ある程度は自分でリスクをコントロールすることもできるのではないだろうか。
ある程度規模のあるウィジェットツールキットを使うほどでもないプログラムであれば、MFC/ATLを使っている部分をWin32 APIで書き換えるのも現実的ではないだろうか。
自作プログラムの場合はある程度規模のあるウィジェットツールキットを使うほどでもなかったがそれなりにコード量があったので、Win32 APIをC++でラッピングしたラッパーを作ることにした。
自分が作成したラッパーの例を置いておく。
自作のラッパーではMFCのCStringクラスをC++のbasic_stringコンテナにTCHARを入れたものに置き換えて文字列の扱いの手間を軽減したり、ダイアログの作成に有用なMFCのDDXで使われるDDX_で始まるマクロに似せたマクロを作ってダイアログ移植の手間を軽減したり、使うコントロールをラップしたクラスを作って面倒なメッセージを使ったWindowsのコントロールの利用の手間を軽減したりしている。また、メッセージループなどのWin32 APIプログラムで定型的に書く必要がある部分とアプリケーション固有の部分の分割も図っている。
実際、MFCを使っていない(と思っていた)Visual Studio上のVisual C++で組んだ自作プログラムをVisual C++ 2010 Expressに移植したところ、リソースファイルがMFCのヘッダファイルをインクルードしていたため、コンパイルエラーが発生するというケースがあった。
そこで、リソースファイルもMFCに依存しないようにするよう、リソースの移植を行った。
今回移植を行ったのは、Visual C++ 6.0で作成したプログラムである。
(おそらく)Visual C++/Studio.NET以降(私が確認したのは.NET 2003と2008である。)では、MFCを使わないようプロジェクト作成時に指定することでリソースエディタのMfc ModeがFalseに設定される。これにより、プロジェクトが生成したリソースファイルがMFCのヘッダファイルをインクルードすることがなくなるので、Visual C++ Express Editionでコンパイルしたときに予期せぬMFCのヘッダファイルのインクルードによりコンパイルエラーが出ることはなくなっている。
以下の本文ではVisual C++ 6.0以前から作成していたMFCを使わないプログラムの移植について取り上げる。
まず、Visual C++ 2010 Expressに存在しないリソースエディタを入手するため、ResEdit Resource Editor - free resource editor for Win32から、ResEditを入手して、インコのWindowsSDK ~リソースエディタResEditの使い方を参考に、セットアップを行った。
次に、リソースファイルをMFCに依存しないよう再編集を行った。
まず、ResEditでリソースファイルを開いた。
これだけでは、afxres.hが存在しないことによりエラーが発生するので、次の対策を採った。
まず、手持ちのVisual Studio 2008 StandardのMFCのヘッダが存在するフォルダをResEditのINCLUDEパスに追加した。
この状態で、リソースファイルを読み込むと既存のリソースファイルの定義をWindows SDKとMFCのヘッダファイルから読み込むので、必要に応じて編集を行った後、ResEditでリソースファイルを保存した。
できたリソースファイルを見ると、afxres.hのインクルードが消えており、リソースファイルがMFCに依存しなくなった。
これで、プログラムがMFCを使わない状態になった。
この状態で、Visual C++ Expressでコンパイルすることで、Visual C++ ExpressでWindows SDKとVisual C++で組んだプログラムをコンパイルすることができるようになった。
次に、元々使っていたVisual Studio.net 2003のVisual C++でコンパイルできるかどうかを確かめて、ソースの移植性を確かめようとしたら、こちらでもエラーが発生した。
調べると、Visual Studio.net 2003のPlatform SDKのwinnt.hには、SUBLANG_JAPANESE_JAPANの定義が存在しないので、エラーが発生しているということがわかった。手元のVisual Studio 2008 Standard付属Windows SDK(Windows Vista用)のwinnt.hにはSUBLANG_JAPANESE_JAPANの定義が存在するので、Visual Studio.net 2003のVisual C++以前の固有の問題であることがわかった。(Visual Studio 2005であればWindows SDKが使えるのでこの問題は発生しない。)
もちろん対処を行う必要があるので、次の対処を行った。
まず、リソースファイルをエディタで開いて、ヘッダファイルをインクルードするところに#include
次に、LANG_JAPANESE_JAPANとあるところをSUBLANG_SYS_DEFAULT(システムのデフォルト)に置き換えた。
この状態でコンパイルを行うことで、Visual Studio.net 2003のVisual C++でもコンパイルが通るようになった。
ソースファイル、リソースファイルの移植ができたら後はコンパイルして動作を確認することになる。
コンパイルの方法は本文の範疇を越えるのでここでは取り上げないことにする。
最後に、今後使用するコンパイラについて考えてみる。
Visual Studioで作ったプログラムの移植先としてはVisual C++ Expressが真っ先に考えられるが、既存の非メトロなプラットフォームで動作するプログラムを作成するためのVisual Studio 2012 Expressの提供予定が当初なかったことを考えると、余裕があれば他の処理系も試してみると良いのではないかと思われる。
コンパイル以外の面ではVisual C++ Expressの機能は貧弱で進歩に乏しいので、そういった面からも他の処理系+IDEの検討も行う価値があるのではないだろうか。