概要
Go言語の cgo バインディングを使って libmecab を呼び出すメソッドです。
珍しい物では無くむしろ良く見かけるのですが、手習いで自作してみました。
他は mecab_nbest_sparse_tostr() を使っているのが多く、それではシングルスレッドでしか使えない物になるため、mecab_lattice_tostr() を使う様にしています。
引っかかったところ
import "C" は include 直下に書く
// #include <mecab.h> // #include <stdio.h> import "C"
import と include の間に空改行挟むと動かないそうです。
ずいぶんなやんだ。
C のポインタ戻りの納め方が良くわかってない
`hoge := C.moga()'
と := で戻り値を受け取ろうとして上手くいかない時があったのですがエラーになるときがあり、そのときどういう型なのか良くわかりませんでした。
単に私の経験不足。
使い方
go install bitbucket.org/rerofumi/mecab
でどーぞ。
ソースコード
mecab-bind.go
package mecab
// #cgo CFLAGS: -I/usr/local/include
// #cgo LDFLAGS: -L/usr/local/lib -lmecab -lstdc++
// #include <mecab.h>
// #include <stdio.h>
import "C"
import "strings"
/* --------------------------------- */
/* --- error define */
/* --------------------------------- */
type mecabError struct {
message string
}
func (err mecabError) Error() string {
return err.message
}
/* --------------------------------- */
/* --- mecab parse */
/* --------------------------------- */
func Parse(line string) (result []string, err error) {
var parse []string
sentence := C.CString(line)
model := C.mecab_model_new2(C.CString(""))
if model == nil {
return parse, mecabError{"mecab model is not created."}
}
mecab := C.mecab_model_new_tagger(model)
if mecab == nil {
return parse, mecabError{"mecab tagger is not created."}
}
lattice := C.mecab_model_new_lattice(model)
if lattice == nil {
return parse, mecabError{"mecab lattice is not created."}
}
C.mecab_lattice_set_sentence(lattice, sentence)
C.mecab_parse_lattice(mecab, lattice)
lines := strings.Split(C.GoString(C.mecab_lattice_tostr(lattice)), "\n")
for _, item := range lines {
if strings.Index(item, "EOS") != 0 {
if len(item) > 1 {
parse = append(parse, item)
}
}
}
C.mecab_destroy(mecab)
C.mecab_lattice_destroy(lattice)
C.mecab_model_destroy(model)
return parse, nil
}
修正履歴
2014/08/12 - 確保した mecab 構造体の解放を忘れていたので追加、メモリ食い尽くして落ちたところで気がついた (;´ Д`)
現状でもエラーリターン時にゴミが残りそうではある。