« 吉里吉里Zで扱われる各種文字コード | メイン | ソースコードのUTF-8化とVisual Studio 2015への移行 »
2016年08月29日
吉里吉里Z 開発:: wchar_t サイズ問題
Tweet @jin1016をフォロー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
};
とする。
Java との受け渡しは jchar ( unsigned short UTF-16 ) か、UTF-8 から変換して渡すメソッドを使う。
Java は UTF-16 なので、jchar で直接渡す方が効率が良さそうではあるが、気にすることのほどではないようにも思う。
投稿者 Takenori : 2016年08月29日 21:59
comments powered by Disqus