カテゴリー別

お絵描き、デザイン

写真、動画関連ソフト

アメーバピグ専用ソフト

ホームページ関連

画像処理

スキャナー用

SEO 関連

お楽しみ

その他

過去ログ

2018年04月03日(火)

WinMain から gtest する方法

SVG エディター ストローク の単体テストは
別のプロジェクトでビルドしていたのですが
二度手間がひどいので統合しました。

ストロークはウィンドウアプリケーション、
一方、単体テストは、gtest を利用しているので
コンソールアプリケーションになります。

作成するアプリケーションのタイプが違うので
別のプロジェクトに分けるのが自然ですが、
無駄に手間がかかるので統合しました。

プロジェクトを分けると、
.cpp や .h ファイルをそれぞれに
追加する必要があって面倒なうえ、
それぞれのプロジェクトで同じファイルを
コンパイルすることになるので時間もかかります。

単体テストとアプリケーションの両方から使う
共通のコードを、まとめた DLL、もしくは lib
を作成するプロジェクトを新たに作成し、
リンクする方法もありますが、
それはそれで面倒です。

なので、一つのプロジェクトを使い、
コンパイルオプションによって
生成されるアプリケーションを
分けることにします。

基本的には、

#define TEST_MODE

#ifdef TEST_MODE
#else
#endif

的なコードで、コンパイルする
コードを分岐していきます。

で、最初に、_tWinMain と _tmain を
コンパイルオプションで切り替えてみたのですが、

error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。

的なエラーになってダメでした。

コンパイルオプションを変えればいけそうですが、
新しいビルドの構成とかするのは、面倒なので却下デス。

しょうがないので、入り口は、_tWinMain のままいきます。

コンソールアプリ用のコマンドライン引数

コマンドライン引数は、 __argc, __argv, __wargv
を使えば OK なので簡単です。

ただし、ユニコードアプリの場合は、
__argv は NULL になるので __wargv を使いましょう。

コンソールを用意する

あとは、コンソールを用意します。

自分のコードを見ると、 AttachCondole に失敗した場合、
AllocConsole してます。たぶん、コンソールからアプリを
起動したときのことを想定してるっぽいです。

で、成功したら、_fileno(stdout) とかが負の場合
freopen_s してます。ファイル名は、CONOUT$ です。

ちなみに、stderr のファイル名は、CONOUT$
stdin のファイル名は、CONIN$ みたいです。
↓ ま、こんな感じです。

if (_fileno(stdout) < 0)
  m_stdout.Reopen("CONOUT$", "w", stdout);
if (_fileno(stderr) < 0)
  m_stderr.Reopen("CONOUT$", "w", stderr);
if (_fileno(stdin) < 0)
  m_stdin.Reopen("CONIN$", "r", stdin);

↑ の自分のコードですが、
そのままはコンパイルできないので、
てきとーに、freopen_s にでも
書き替えてくださいな。

AttachConsole とか、AllocConsole に成功してる場合は、
プログラム終了前に FreeConsole する必要があるみたいですね。

あ、コンソールに日本語を出したい場合は、

std::wcout.imbue(std::locale("", std::locale::ctype));
std::wcerr.imbue(std::locale("", std::locale::ctype));

とかした方がいいかもね。

gtest の呼び出し

あとは、普通に gtest を呼びだせば OK です。

::testing::InitGoogleTest(&__argc, __wargv);
int ret = RUN_ALL_TESTS();

ま、こんな感じか。

ストローク
ストローク ダウンロード
ストローク サンプル画像
ストローク 更新履歴
ご意見・ご要望連絡窓口


コメント
コメントする