MeCabをRuby 1.9.2 on Windows7(64bit版)で使う方法
Windows7の開発環境を構築するに当たって、なんとなくRubyを1.8.7から1.9.2にしてみました。
そしたら意外とx64でMeCabを使えるようになるまでにハマったのでメモしておきます。
Makefileとかよく分からないなりに頑張ったのですが、かなりいい加減だと思います。
方針としては、libmecab.dllをx64環境でコンパイルしなおして、次のサイトを参考にしてmecab.rbを作ります。(ついでに、元々の言語処理関連のプログラム類 で実装されていたsparse_tonode(str)も使えるようにさせていただきました。ありがとうございます! )
Windowsのrubyでmecab | アッセんぶら 困ぱいる
- Windows版のMeCabをとりあえず入れておく。
- MeCabのソースを入手し、展開する。
- src以下にある、mecab.h, feaure_index.cpp, wrier.cpp, Makefile.msvc.inを修正する
mecab.h
・254行目#ifndef SIWG
→#ifndef SWIG
・257行目#endif
を 260行目の};
の前の行に挿入 feaure_index.cpp
・311行目case 't': os_ \<\< (size_t)path-\>rnode-\>char_type; break;
→case 't': os_ \<\< (unsigned int)path-\>rnode-\>char_type; break;
wrier.cpp
・236行目case 'L': \*os \<\< std::strlen(sentence); break;
→case 'L': \*os \<\< (unsigned int)std::strlen(sentence); break;
Makefile.msvc.in → Makefile.msvcにファイル名変更
・5行目 /MACHINE:X86
→ /MACHINE:X64
・7行目、8行目
DDIC_VERSION=@DIC_VERSION@
→ -DDIC_VERSION=102
DVERSION=”\”@VERSION@”\”"
→ -DVERSION=“\”0.98″\”"
2011/01/11追記:
Visual Studio 2010ではcommon.hに #include
詳しくはこちらを参照(Thanks to id:mayukiさん!)
Visual Studio 2008 x64 Cross Tool コマンドプロンプトでnmake
できたlibmecab.dllをlibmecab64.dllなど適当な名前にして、libmecab.dllと同じフォルダに移動
Windowsのrubyでmecab | アッセんぶら 困ぱいる と言語処理関連のプログラム類を参考にしてmecab.rbを作成
# -*- coding: windows-31j -*-
require "dl/import"
require "dl/struct"
module MecabFunc
extend DL::Importer
dlload 'libmecab64.dllの場所'
typealias('size_t', 'unsigned long')
extern "mecab_t\* mecab_new2(const char\*)"
extern "const char\* mecab_version()"
extern "const char\* mecab_sparse_tostr(mecab_t\*, const char\*)"
extern "const char\* mecab_strerror(mecab_t\*)"
extern "void mecab_destroy(mecab_t \*)"
end
module MecabLib
class Mecab
include MecabFunc
@mecab=nil
def initialize(args)
@mecab=MecabFunc.mecab_new2(args)
end
def version()
MecabFunc.mecab_version()
end
def strerror()
MecabFunc.mecab_strerror(@mecab)
end
def sparse_tostr(str)
MecabFunc.mecab_sparse_tostr(@mecab,str)
end
def sparse_tonode(str)
#http://nlp.sfc.keio.ac.jp/~aihara/nlp.html でのaihara氏の実装です。
prev=nil
head=Node.new()
tmp_str= "#{sparse_tostr(str)}"
tmp_str.split("\n").each{|line|
buf=Node.new(line,prev)
if prev!=nil
prev.next=buf
end
prev=buf
if head.next==nil
head.next=buf
end
}
head
end
def destroy()
MecabFunc.mecab_destroy(@mecab)
end
class Node
@prev=nil
@next=nil
@surface=nil #形態素の表記
@pos=nil #品詞
@root=nil #原形
@reading=nil #読み
@pronunciation=nil #発音
attr_accessor :prev,:next,:surface,:pos,:root,:reading,:pronunciation
def initialize(line=nil, prev=nil)
@prev=prev if line != nil
if line == "EOS" #EOSの時
@surface=line
@pos="EOS"
@root="EOS"
@reading="EOS"
@pronunciation="EOS"
else #それ以外
linels=line.split("\t")
@surface=linels[0]
fetls=linels[1].split(",")
@pos=fetls[0..5].join(",")
if fetls[6]==nil
@root=""
else
@root=fetls[6]
end
if fetls[7]==nil
@reading=""
else
@reading=fetls[7]
end
if fetls[8]==nil
@pronunciation=""
else
@pronunciation=fetls[8] end
end
end
end
def hasNext()
if @next==nil
false
else
true
end
end
end
end
end
mecab.rbの名前をmecab64.rbとでもつけます。実際に呼ぶときは、RUBY_VERSIONで切り替えたりしています。
# -*- coding: windows-31j -*-
require "mecab64"
m = MecabLib::Mecab.new("")
puts m.version
puts m.sparse_tostr("本日は晴天なり。")
node = m.sparse_tonode("本日は晴天なり。")
while node.hasNext
node = node.next
print node.surface + " : " + node.pos + " : " + node.root + " : " + node.reading + " : " + node.pronunciation + "\n"
end
とすると、次のような結果が出るはずです。
0.98
本日 名詞,副詞可能,*,*,*,*,本日,ホンジツ,ホンジツ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
晴天 名詞,一般,*,*,*,*,晴天,セイテン,セイテン
なり 助動詞,*,*,*,文語・ナリ,基本形,なり,ナリ,ナリ
。 記号,句点,*,*,*,*,。,。,。
EOS
本日 : 名詞,副詞可能,*,*,*,* : 本日 : ホンジツ : ホンジツ
は : 助詞,係助詞,*,*,*,* : は : ハ : ワ
晴天 : 名詞,一般,*,*,*,* : 晴天 : セイテン : セイテン
なり : 助動詞,*,*,*,文語・ナリ,基本形 : なり : ナリ : ナリ
。 : 記号,句点,*,*,*,* : 。 : 。 : 。
EOS : EOS : EOS : EOS : EOS