« 吉里吉里Zで扱われる各種文字コード | メイン | ソースコードのUTF-8化とVisual Studio 2015への移行 »

2016年08月29日

吉里吉里Z 開発:: wchar_t サイズ問題

    

wchar_t は、Android では 4バイトで Windows では 2バイト。
コンパイラのオプションで変更は出来るが、意図しない問題が発生する可能性があるため、それは好ましくない。
サイズ依存しないように対応することも出来るが、注意しないと問題が発生する可能性があるのと、テキスト ( スクリプト ) 読み書き等ファイルアクセスする時毎回変換が入る ( セーブデータが環境ごとに異ならないようにするためと UTF-16LE のスクリプト対応 ) 。

どうするか?

・tjs_char の定義を wchar_t ではなく、char16_t に変更する。
・定数文字列は L"" ではなく、u"" とする。
・std::wstring は std::u16string を使用 ( tjs::string などと定義 ) する。
・文字列処理の標準ライブラリは、自前で準備する ( Bionic から持ってきて書き換える、TJS_xxx マクロを関数化 ) 。

これで問題なくなるはずなので、この方法で対処を試みる。


以下、char16_t を知らなかったので、色々検討していたことだけど、無駄だった。

吉里吉里では tjs_char を使用しているので、Android などでは typedef tjs_char unsigned short として、文字列処理関数類は Bionic から持ってくるのが良いのではないかと最初考えた。
文字列処理関数も TJS_xxx と言った名前が使われているため、define で別名を与えるのではなく、別実装としてしまえば問題ない。
また、文字列処理関数も SIMD 化可能なので、SIMD 化する時も都合が良い。

ただし、この対応でも実行ファイル内文字コードの問題が解決しないことに気付いた。
TJS_W で埋め込んでいるが、これは L"" で wchar_t の文字列であり、サイズ問題が発生する。
文字列の埋め込みは極力止めて、リソースに文字列を逃がし、多言語対応するようにしているが完全ではない。

1. 文字列の埋め込みは極力行わずリソースに格納する。
2. L"" の使用は中止し、"" に変更を行い実行ファイル内文字コードは UTF-8 とし、必要に応じて UTF-8 から UTF-16 に変換を行う。

1番はいいとして、2番の判断をどうするか。
注意を必要とするが問題ないと思えたものの、__TIME__ などの定義済みマクロを使用する箇所で変更が必要。

-fwide-exec-charset で utf-16 にするか? これはコンパイルオプションと同じく注意が必要になる。

TJS_W を非 Windows 環境では関数とし、非ワイド文字 ( UTF-8 ) を受け取り、UTF-16 を返すようにする。
受け取るのは定数なのはわかっているので、変換テーブルを持って対応する。
うまく行きそうだが少しトリッキー。

std::wstring 問題も残る。
namespace tjs {
typedef basic_string string;
};
とする。

Java との受け渡しは jchar ( unsigned short UTF-16 ) か、UTF-8 から変換して渡すメソッドを使う。
Java は UTF-16 なので、jchar で直接渡す方が効率が良さそうではあるが、気にすることのほどではないようにも思う。


投稿者 Takenori : 2016年08月29日 21:59




comments powered by Disqus
Total : Today : Yesterday : なかのひと