mingw32での「undefined reference to `WinMain@16'」
Unicode有効(-DUNICODE -D_UNICODE
)時に下記のコードをmingw32-gccでビルドしようとすると"WinMain"が未定義ですという旨のリンクエラーが出てしまう。
$ gcc -o foobar.exe foobar.c -D_UNICODE -DUNICODE -mwindows -lmingw32 -lkernel32
/usr/i686-pc-mingw32/sys-root/mingw/lib/libmingw32.a(main.o):(.text+0xd2): undefined reference to `WinMain@16'
$
解決策はint main(int, char**)
を定義するべし。これはぐぐれば比較的容易に発見可能。では、なぜか?という点の解説は日本語のページにはあまりないようだ。
ANSI版WinMainの場合
コンパイルオプションから-D_UNICODE -DUNICODE
を抜くとANSI版でコンパイルされる。このとき問題なくコンパイルされ、(Unicode対応していない点を除いて)正常に動作する。
$ gcc -o foobar.exe foobar.c -mwindows -lmingw32 -lkernel32
$
このコンパイルオプションとき、TCHAR
はCHAR
に、_tWinMain
関数はWinMain
関数とみなされる。これはtchar.h
での単純な#define
で実現されている。
そしてこのとき、エントリーポイントWinMain
から実行されることとなり、実際そのように動作する。
Unicode版wWinMainの場合
冒頭で示したUnicodeのコンパイルオプションのとき、TCHAR
はWCHAR
に、_tWinMain
関数はwWinMain
関数とみなされるのが正しい動作である。同様にtchar.h
を参照すると下記の通りになっている。
ここにはmingw32 が「no wide startup module(Unicode向けスタートアップモジュールが未実装)」だということがかかれている。つまり、プログラムやコンパイルオプションなどは正しいが、mingw32 の未実装機能を使っているコードになっているのが正確な回答であって、簡単に言えば_tWinMain
およびwWinMain
は mingw32 では現状使用できないのである。この対策としてmain
関数をエントリーポイントにすることが多く行われるようである。
この面倒くさい説明を省いた結果、代替策の一つであるWinMain
の代わりにmain
関数の利用が解決策として提示されることになったようである。
解決策の事例はUnicodeでMingw32の落とし穴〜_tWinMain/wWinMain問題など〜に書きました。
参考文献
- mingw32-runtime 3.15.2 付属の
tchar.h
- Re: [Mingw-users] link error when using _tmain