CharSet.Ansiで渡されるものは?
DllImportで文字列を渡す場合、何の文字コードでエンコードされるべきなんでしょうか? 例えば、
ファイル:foo.c
#include <stdio.h> __declspec(dllexport) void Say(const char* msg) { printf("say 「%s」\n", msg); }
コンパイルして、foo.dllを作りました。
> cl /LD foo.c
で、こいつをP/InvokeでC#から呼び出します。
ファイル:bar.cs
using System; using System.Text; using System.Runtime.InteropServices; public class Bar { [DllImport("foo", CharSet=CharSet.Ansi)] static extern void Say(string msg); public static void Main() { Console.WriteLine(Encoding.Default.WebName); Say("こんにちは"); } }
こんな感じで呼び出すコードを書いてコンパイル。
> mcs -codepage:932 bar.cs
mcsのデフォルトはutf-8なのでsjisでソースコード書いた場合は、コードページを指定する必要があるので注意です。
で、早速、bar.exeを実行します。
> mono bar.exe shift_jis say 「縺薙s縺ォ縺。縺ッ」
化け化けちゃん。これはmonoの場合、CharSet.Ansiの扱いが(多分)utf-8となっているためです。ちなみに.NET1.1上で実行すると、
> bar.exe shift_jis say 「こんにちは」
ちゃんと表示されます。MSDNのドキュメントによるとCharSet.Ansiの扱いは、
マルチバイト文字として文字列をマーシャリングします。
と、あります。文字コードについて特に規定はされてないようですが、個人的にはEncoding.Defaultあたりが使われるのが自然な気がします。ただ、Linuxだとどうなるのか?とか、日本語以外の言語はどーなるのか?が分かってないのですけど。(^^;
(追記)
id:ladybugさんのコメントから。
> Mono はどうしてるのかしら?
ちょっとソース見たところ、glibのg_get_charsetを呼び出しているみたいです。
ただ、マーシャリング時のString -> Ansiの場合、
gpointer ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string) { MONO_ARCH_SAVE_REGS; return mono_string_to_utf8 (string); }
これを使っている気がします。きちんと調べてないんですけど。(^^; もし、これなら、utf-8固定ですよね?