PInvoke と文字コード
次のような2つのメソッドを考える。
[DllImport("test.dll", CharSet=CharSet.Auto)] extern void Test1(string msg); [DllImport("test.dll", CharSet=CharSet.Auto)] extern void Test2(IntPtr buffer, int size);
前者には小さな問題はあるが大きな問題はない。
test.dll が Ansi 用のエントリポイントしか提供しなければ、引数 msg は現在スレッドのカルチャと OS の文字セットに従った ANSI コードにマーシャリングされるし、Unicode 用のエントリポイントを持っていれば文字コードの変換なしに、いわゆる C-String としてポインタだけが渡される。
問題は、以前、GDNJ の掲示板でも書いたが、後者の buffer に対して文字列を渡したい場合である。
IntPtr 型の変数に適切にメモリを割り当て、手動でエンコードをあわせてマーシャリングする……それだけのことなのだが、Test2 が test.dll において Ansi 用のエントリポイントに解決されたのか、Unicode 用のエントリポイントに解決されたのか、判断する手段がない。
Marshal クラスには、明示的に Ansi/Unicode を指定しない StringToHGlobalAuto() や StringToCoTaskMemAuto() というメソッドがあるが、こいつらには何も期待できない。
こいつらは、あらかじめ Marshal クラスが初期化されたときに決定*1された Ansi/Unicode の種別を用いて、同Ansi() および 同Unicode() を呼び分けるだけである。