BLOGサブスレッドの日常

2016.06.07

いまさら tchar.h に学ぶコード互換性

tama

明日は技術試験があるし早く寝ようと思った6日27:30。
( ゚д゚)ハッ! 今日あたしブログ担当だったじゃん!忘れてt

というわけでネタを絞り出してきました、月曜日の tama です。はろー

最近社内での圧力に屈してPython3に着手しまして(2.3の頃からずっと2.x派だった)。
いやだって 3.0 が出たとき「これはPython界のHoneycombや…!」と思ったんだもの。
すぐにICSこと 4.0 が出てそっちに収斂すると思ったのだもの。
読みが外れて時代は 3.x らしいので、これまでの 2.7対応のコードを 3.4対応にリファクタリング。

個人的に楽しいなと思ったのは 2.7 & 3.4 両対応のコードを書くというシーン。
文法レベルの拡張構文(例えば from . import localmodule とか)は 2.6,7 あたりから
移行準備的に用意されていたりするので基本的に言語仕様上の大きな問題はない、、はず。

こういう、ひとつのコードで異なるコンパイラやインタプリタ、あるいは複数のプラットフォームや
ビルド条件に対応するケースはよくあると思います。
OSSだと autoconf や automake(Autotools)を使ったりするのかしらん?(知識が古いかも)
WindowsでC++してた頃は _MBCS と _UNICODE に対応するために tchar.h にお世話になっていました。

tchar.h

そもそも _MBCS とか _UNICODE とは、っていう話はそれぞれ身近な生き字引きに聞いてください。
弊社では広島と名古屋にひとりずつ生き字引きポジションのおっさんを配備しています。

  • _MBCS → 文字列はASCIIベースのキャラセット(MultiByte CharSet)で指定する。
    • Windowsにとっての標準は UTF-8 ではない。日本語の場合は Shift-JIS ベースの CodePage932
  • _UNICODE → 文字列はUNICODEで指定する。

文字列を引数に取るような Windows API は、基本的にサフィックスAの付いたMBCS版と
サフィックスWが付いたUNICODE版があります。
CreateWindowA() と CreateWindowW() という具合です。
これを共通の CreateWindow() に見せてくれているのが tchar.h なのです。

イメージはこんな感じです。

#ifdef _UNICODE
# define CreateWindow CreateWindowW
#else
# define CreateWindow CreateWindowA
#endif

一文字を表す型もちゃんと用意されています。 _TCHAR です。
_MBCS の場合は1文字は1byte(ASCIIの場合)なので _TCHAR は char です。
_UNICODE の場合は1文字はUNICODE 1文字なので wchar_t です。

文字列を表す型は次の通り定義されています。

tchar.h 定義 _MBCS _UNICODE
文字列 PTSTR
(_TCHAR*)
PSTR
(char*)
PWSTR
(wchar_t*)
const文字列 PCTSTR
(const TCHAR*)
PCSTR
(const char*)
PCWSTR
(const wchar_t*)

頭の P はポインタの意味です。これを LP と書く人はおっさんです。どういう意味かは生き字引き(ry
このほか C は const、T は TCHAR、W は wide char を示しています。

このあたり理解せず混同しているようなブログ記事もちょいちょい見かけるので注意が必要です。
CreateWindowA()の引数は PCSTR であり、PCTSTR ではありません。
逆に CreateWindow()に PCSTR や PSTR を渡すと _UNICODE なビルドでエラーしてしまいます。

MicrosoftはTCHAR対応をがんばっていて、 str__XXX__() 系の標準関数ひとつひとつにも
対応する wide char版の wcs__XXX__() と明示的にMBCS版の _mbs__XXX__()、
それとTCHAR版の _tcs__XXX__() を用意しています。
wcscpy()、_mbscpy()、_tcscpy() という具合です。
どうぞぜひ自分で調べて違いを確認してみてください。

まとめ(?)

1ソースで複数のプラットフォームに対応するためのカラクリの内側を見るのはおもしろいよね、という話でした。
ネムイ(´・ωゞ)

この記事を書いた人

tama