Contents Up Previous Next

wxWidgets における Unicode 対応

この章では wxWidgets における Unicode の対応状況について簡潔に述べます。英語以外の言語で使用される文字を扱うプログラムを書く方法について、より詳しく知りたい場合はこの章を読んでください。

Unicode とは?
Unicode モードと ANSI モード
wxWidgets における Unicode 対応
Unicode と外部の世界
Unicode 関連のコンパイル設定


Unicode とは?

wxWidgets は Unicode に対応しているプラットフォームであれば Unicode モードでコンパイルすることが可能です。Unicode とは、 1 文字あたり少なくとも 16 (あるいは 32) ビットを使用することで、これまでの標準的な 8 ビットの文字コードの欠点に対処した文字コードの標準規格のことです。これにより、 通常の 256 文字の代わりに少なくとも 65536 文字 (これはBMP、もしくは基本多言語面と呼ばれます) 、あるいは 2^32 文字を表現することが可能であり、これは世界中の言語を一度に表現するのに十分な量です。Unicode についての詳細は www.unicode.org にあります。

この解決策は明らかにこれまでのものより望ましい (同じ言語の互換性のない文字コード、混沌としたロケールなどを想像してみてください) ため、多くのモダンなオペレーティングシステムでは Unicode をサポートしています。おそらく、最初の例は Windows NT でしょう。 Windows NT ではかなり初期のバージョンから内部的に Unicode を使用しています。

Unicode を使うことで、国際化対応のプログラムをより簡単に書くことができます。そして、 Unicode 対応が進むにつれ、それはますます簡単になっていくことでしょう。さらに Windows NT/2000 の場合、標準的な ASCII モードのみを使用するプログラムであっても Unicode の恩恵を得ることができます。 なぜなら、システムコールを実行するたびにすべての文字列を Unicode に/から 変換する必要がないため、より効率的にプログラムが動作できるためです。


Unicode モードと ANSI モード

wxWidgets の対応しているすべてのプラットフォームで Unicode が (完全に) サポートされているわけではないため、Unicode 環境でのみ動作するプログラムを書くのは多くの場合で賢明ではないでしょう。より良い解決策としては、(従来の) ANSI モードと Unicode モードのどちらでもコンパイルできるようにプログラムを書くことです。

これは wxWidgets の提供する方法を使うことで極めて単純に実現することができます。基本的には、気をつけなければならないことはごく僅かです。

それではこれらを順番に見ていきましょう。最初に、プログラム中の文字について、通常であれば 1 文字あたり 1 バイトですが、Unicode プログラムの場合 2 バイトを消費するため、文字を格納するために別の型を使用する必要があります。 (char 型は通常 1 バイトしか保持できません) この型のことを wchar_t と呼び、wide-character type の略です。

また、文字列や文字定数は char (1 バイト) の代わりにワイド文字 (wchar_t 型、通常 2 か 4 バイト) で符号化される必要があります。これは標準的な C (および C++) の方法で実現されます: 文字列定数の後ろに 'L' という文字を配置するだけで、 long 定数、すなわちワイド文字になります。もう少しだけ可読性を上げるために、 'L' を定数の後ろではなく、前に付けることも可能です。

もちろん、普通の標準 C 関数は wchar_t 文字列をうまく取り扱うことができません。そのため、char * の代わりに wchar_t * を受け取る別の関数群が用意されています。例えば、ワイド文字列の長さを取得する関数は wcslen() と呼ばれます。(strlen() と比べると、違いは "string" を表す接頭語 "str" が "wide-character string" を表す "wcs" に変わっているだけであることが分かると思います)

最後に、上に挙げた標準プリプロセッサトークンは ANSI 文字列として展開されますが、Unicode ビルドの際には Unicode 文字列の方が必要なことが多いでしょう。wxWidgets では __TFILE____TDATE____TTIME__ マクロを提供しており、これらは ANSI ビルド時には ANSI 文字列に、 Unicode ビルド時には Unicode 文字列になることを除き、標準トークンとまったく同じに振る舞います。

要点をまとめるため、 ANSI モードと Unicode モードの両方でコンパイルできるプログラムの簡潔な例を以下に示します。

#if wxUSE_UNICODE
    wchar_t wch = L'*';
    const wchar_t *ws = L"Hello, world!";
    int len = wcslen(ws);

    wprintf(L"Compiled at %s\n", __TDATE__);
#else // ANSI
    char ch = '*';
    const char *s = "Hello, world!";
    int len = strlen(s);

    printf("Compiled at %s\n", __DATE__);
#endif // Unicode/ANSI
もちろん、この方法でプログラムを書くのは不可能に近いでしょう。 (平均的なプログラムに含まれることになるであろう #ifdef UNICODE の数を想像してみてください!) 幸運なことに、別の方法があります。次の章を参照してください。


wxWidgets における Unicode 対応

wxWidgets では、上記のコードの代わりに以下のように書きます

    wxChar ch = wxT('*');
    wxString s = wxT("Hello, world!");
    int len = s.Len();
ここでは何が起きているのでしょうか? 最初に、#ifdef がまったくないことが分かると思います。その代わり、Unicode ビルドと ANSI ビルドで異なる振る舞いをする型とマクロが定義されており、これによってプログラム内で条件付きコンパイルを使用しなくても済みます。

wxChar 型はコンパイル時のモードによって charwchar_t のいずれかにマッピングされます。だからといって、文字列に別々の型を使用する必要はありません。なぜなら、標準の wxString が Unicode に対応している (コンパイルモードに応じて ANSI 文字列か Unicode 文字列を格納する) ためです。

最後に、プログラム中のリテラル文字列を囲む、特別な wxT() マクロがあります。最後の部分を上記の例と比較すると簡単に分かるように、このマクロは (通常の) ANSI モードでは何も起こりませんが、Unicode モードでは引数の接頭語 'L' として展開されます。

重要な結論としては、char の代わりに wxChar を使い、 C 形式の文字列ではなく wxString を使い、すべてのリテラル文字列を wxT() マクロで囲むのを忘れなければ、あなたのプログラムは自動的に (ほぼ) Unicode 準拠になるということです!

もう一度だけルールを述べさせてください:


Unicode と外部の世界

すでに見てきたように、wxWidgets の型とマクロを使用することで簡単に Unicode プログラムを書くことができます。しかし、それで十分ではないことについても述べてきました。. プログラム内部ではすべてうまく動作するとしても、外部の世界とやり取りしようとすると、それらは悲しいことにしばしば ANSI 文字列を想定しているため、ひどいことになります。 (特筆すべき例外として、すべての Win32 API は Unicode 文字列と ANSI 文字列の両方を受け付けるため、プログラム内でなんらかの変換を行う必要がまったくありません)GTK 2.0 は UTF-8 文字列のみを受け付けます。

wxString から ANSI 文字列を取得するには、常に ANSI 文字列を返却する mb_str() 関数を使用することができます。 (これはビルドモードに依存しません。一方で、普通の c_str() は内部の表現型のポインタを返却しますが、これは ASCII か Unicode のどちらかです) めったに使われませんが、便利な関数として wc_str() 関数があり、これは常に Unicode 文字列を返却します。

時々、ANSI 文字列を wxString に変換する必要があります。この場合、以下の変換コンストラクタを使用することができます:

   const char* ascii_str = "Some text";
   wxString str(ascii_str, wxConvUTF8);
このコードは非 Unicode ビルドでも正常にコンパイルすることができますが、変換自体は行われません。

Unicode の変換についての詳細は wxMBConv クラスの概要 を参照してください。


Unicode 関連のコンパイル設定

プログラムを Unicode モードでコンパイルする場合、 wxUSE_UNICODE を 1 に定義する必要があります。これは今のところ、wxMSW、wxGTK、wxMac、wxX11 で動作します。プログラムを ANSI モードでコンパイルした場合でも、 wxUSE_WCHAR_T を定義することで wchar_t の限定的な機能を利用することができます。

これにより、あなたのプログラムの中で (wxMBConv クラスを利用した) Unicode 文字列と ANSI 文字列の変換や、(おそらく外部ファイルや他の場所から読み込んだ) Unicode 文字列から wxString オブジェクトを作成することができます。