WindowsでUTFを使う
Dの文字列は、UTF文字列です。 Microsoft Windows の API は通常、入力文字列の受け取り方に応じて、 関数ごとに二つのバージョン - "A" バージョンと "W" バージョンが用意されています。"W" バージョンは UTF-16 を文字列引数の形式として受け取るので、D の wchar[] 文字列と直接対応します。しかし、比較的初期の Windows では、 多くのAPI関数の "W" バージョンが実装されていません。 かといって、"A" バージョンを使うのも問題があります。"A" バージョンは 環境ごとの様々な文字エンコード方式を扱うので、 UTF-8 形式である D の char[] 文字列と、 直接の互換性を持っていないのです。
この問題に対処する正しい方法は、まず、"W" バージョンに対応した バージョンの Windows であるかどうか判別し、非対応であれば、 wchar[] 文字列を "A" バージョンで扱える形式に変換することです。 この方法は Phobos ランタイムライブラリで使用されており、 以下のようになっています:
private import std.c.windows.windows; private import std.utf; int useWfuncs = 1; static this() { // Win 95, 98, ME では W 関数は実装されていない useWfuncs = (GetVersion() < 0x80000000); } char* toMBSz(char[] s) { // 最上位ビットが立っている文字があるときのみ変換が必要 foreach (char c; s) { if (c >= 0x80) { char[] result; int i; wchar* ws = std.utf.toUTF16z(s); result.length = WideCharToMultiByte(0, 0, ws, -1, null, 0, null, null); i = WideCharToMultiByte(0, 0, ws, -1, result, result.length, null, null); assert(i == result.length); return result; } } return std.string.toStringz(s); } uint getAttributes(char[] name) { uint result; if (useWfuncs) result = GetFileAttributesW(std.utf.toUTF16z(name)); else result = GetFileAttributesA(toMBSz(name)); return result; }