MeCabをRuby 1.9.2 on Windows7(64bit版)で使う方法

2010-10-13·
Aki Ariga
Aki Ariga
· 3 min read

Windows7の開発環境を構築するに当たって、なんとなくRubyを1.8.7から1.9.2にしてみました。
そしたら意外とx64でMeCabを使えるようになるまでにハマったのでメモしておきます。
Makefileとかよく分からないなりに頑張ったのですが、かなりいい加減だと思います。

方針としては、libmecab.dllをx64環境でコンパイルしなおして、次のサイトを参考にしてmecab.rbを作ります。(ついでに、元々の言語処理関連のプログラム類 で実装されていたsparse_tonode(str)も使えるようにさせていただきました。ありがとうございます! )
Windowsのrubyでmecab | アッセんぶら 困ぱいる

  1. Windows版のMeCabをとりあえず入れておく。
  2. MeCabのソースを入手し、展開する。
  3. 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さん!)

  1. Visual Studio 2008 x64 Cross Tool コマンドプロンプトでnmake

  2. できたlibmecab.dllをlibmecab64.dllなど適当な名前にして、libmecab.dllと同じフォルダに移動

  3. 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

Aki Ariga
Authors
Principal Software Engineer
Interested in Machine Learning, ML Ops, and Data driven business. If you like my blog post, I’m glad if you can buy me a tea 😉

Related