C#でMecabをVista上でも動かす
あちこちのページを見ながらMecabをC#で取り込んで動かしていたのだが、Vista環境になったら動かなくなった。XPでは動いたんだよ。
XPでは動くコード。*1
using System.Runtime.InteropServices; public partial class Form1 : Form { [DllImport("libmecab.dll")] extern static int mecab_new2(string arg); [DllImport("libmecab.dll")] extern static string mecab_sparse_tostr(int m, string str); [DllImport("libmecab.dll")] extern static void mecab_destroy(int m); private void button1_Click(object sender, EventArgs e) { int mecab = mecab_new2(""); string s = mecab_sparse_tostr(mecab,textBox1.Text); mecab_destroy(mecab); textBox2.Text = s; } }
XPでは問題なく動くのだが、Vistaにすると
mecab_sparse_tostr(mecab,textBox1.Text); で
System.AccessViolationException はハンドルされませんでした。
Message="保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。"
と意味不明なエラーが出る。
改良版
[DllImport("libmecab.dll")] extern static IntPtr mecab_new2(string arg); [DllImport("libmecab.dll")] extern static IntPtr mecab_sparse_tostr(IntPtr m, string str); [DllImport("libmecab.dll")] extern static void mecab_destroy(IntPtr m); private void button1_Click(object sender, EventArgs e) { IntPtr mecab = mecab_new2(""); IntPtr s = mecab_sparse_tostr(mecab, textBox1.Text); textBox2.Text = Marshal.PtrToStringAnsi(s); mecab_destroy(mecab); }
mecab_sparse_tostrの返値をIntPtrに変更して、それをMarshal.PtrToStringAnsiで文字列に変換する。
これでXPとVista両方で動いた。Stringの変換に失敗していたくさい。トリッキーすぎるよ・・・。
教えてくれた2chのスレの人、ありがとう。躓く人が出てくると思うので書いた。
追記 これでは不十分でMarshal.PtrToStringAnsi(s);の前にsのNullチェックをしないとだめ。C#でMecabがいきなり落ちる問題 - どうせポエムですよっと