Skip to content

Instantly share code, notes, and snippets.

@shiumachi
Last active December 25, 2015 11:59
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shiumachi/6972974 to your computer and use it in GitHub Desktop.
Save shiumachi/6972974 to your computer and use it in GitHub Desktop.
#gocon 2013 Autumn での成果物。
* go のコンパイル
brew のインストールファイルにはファイルが欠けているものがあるので、ソースから go をビルドする必要がある
ソースは以下のコマンドでとってこれる。
$ hg clone -u release https://code.google.com/p/go
GOROOTの変更を忘れずに。
$ GOROOT=${HOME}/src/go
mecab とのリンクには 32bit アーキテクチャでコンパイルする必要がある。
(注: 後でコンパイルしたらアーキテクチャ指定しなくてもよかったので、実はいらない可能性がある。ここでは記録のため残しておく)
$ cd $GOROOT/src
$ GOARCH=386 bash make.bash
$ bash make.bash
(x86_64 用。こうするとこっちがデフォルトになる)
これでx86用コンパイラができる。
コンパイルは以下のように行う。
# GOARCH=386 go build
ソースコードからのコンパイルは下記リンクを参照
http://golang.org/doc/install/source
* mecab のコンパイル
mecab のコンパイルにはいくつかのオプションが必要。
http://mecab.googlecode.com/svn/trunk/mecab/doc/libmecab.html
ここを参照に、以下のコマンドを実行する。
$ mecab-config --cflags
-I/usr/local/Cellar/mecab/0.996/include
$ mecab-config --libs
-L/usr/local/Cellar/mecab/0.996/lib -lmecab -lstdc++
これらを go 内の C のコードに追加する。
/*
#cgo CFLAGS: -I/usr/local/Cellar/mecab/0.996/include
#cgo LDFLAGS: -L/usr/local/Cellar/mecab/0.996/lib -lmecab -lstdc++
#include <mecab.h>
struct mecab_t {};
*/
import "C"
これを設定したら、go install でコンパイルする。
CGO_ENABLED=1 go install ./mecab-bin
* cgo の基本
/*
C のコード ….
*/
import "C"
という風にコメントに書く。今回使うコードは先述の通り。
C.(型、関数、構造体) の形式でほとんど何でも使える。
例:
C.mecab_new2(ptr)
C と Go の間でプリミティブ型に全て互換性があるわけじゃないので、データのやりとりには型変換が必要。
文字列の場合
Go から C
p := C.CString(s)
C から Go
ret_val := C.GoString(ptr)
int型
C から Go
int(c_int)
* cgo のコンパイル
なぜか main 関数が同一パッケージだとコンパイルできないので注意
(他に方法があるかもしれないが分からなかった)
package main
import "fmt"
import "mecab"
import "os"
func main() {
fmt.Printf("hello, world\n")
var s2 string
if len(os.Args) != 2 {
fmt.Printf("usage: mecab-bin [string]\n")
s2 = "今日、僕は新橋でビール片手に壁を上った。"
} else {
s2 = os.Args[1]
}
m := mecab.New2("")
fmt.Printf("--- SparseToStr ---\n")
r := mecab.SparseToStr(m, s2)
fmt.Printf("result: \n%s\n", r)
fmt.Printf("--- NBestSparseToStr(num: 3) ---\n")
r = mecab.NBestSparseToStr(m, 3, s2)
fmt.Printf("result: \n%s\n", r)
fmt.Printf("--- DumpNode ---\n")
n := mecab.SparseToNode(m, s2)
mecab.DumpNode(n)
}
package mecab
import "fmt"
/*
#cgo CFLAGS: -I/usr/local/Cellar/mecab/0.996/include
#cgo LDFLAGS: -L/usr/local/Cellar/mecab/0.996/lib -lmecab -lstdc++
#include <mecab.h>
struct mecab_t {};
*/
import "C"
func New2(s string) *C.mecab_t {
p := C.CString(s)
m := C.mecab_new2(p)
return m
}
/*
http://mecab.googlecode.com/svn/trunk/mecab/doc/libmecab.html
// Gets tagged result in string.
result = mecab_sparse_tostr(mecab, input);
CHECK(result)
printf ("INPUT: %s\n", input);
printf ("RESULT:\n%s", result);
*/
func SparseToStr(m *C.mecab_t, s string) string {
p := C.CString(s)
r := C.mecab_sparse_tostr(m, p)
ret_val := C.GoString(r)
return ret_val
}
/*
http://mecab.googlecode.com/svn/trunk/mecab/doc/libmecab.html
// Gets N best results
result = mecab_nbest_sparse_tostr (mecab, 3, input);
CHECK(result);
fprintf (stdout, "NBEST:\n%s", result);
*/
func NBestSparseToStr(m *C.mecab_t, num int, input string) string {
p := C.CString(input)
c_num := C.size_t(num)
r := C.mecab_nbest_sparse_tostr(m, c_num, p)
ret_val := C.GoString(r)
return ret_val
}
/*
http://mecab.googlecode.com/svn/trunk/mecab/doc/libmecab.html
node = mecab_sparse_tonode(mecab, input);
CHECK(node);
for (; node; node = node->next) {
if (node->stat == MECAB_NOR_NODE || node->stat == MECAB_UNK_NODE) {
fwrite (node->surface, sizeof(char), node->length, stdout);
printf("\t%s\n", node->feature);
}
}
*/
func SparseToNode(m *C.mecab_t, input string) *C.mecab_node_t {
p := C.CString(input)
node := C.mecab_sparse_tonode(m, p)
return node
}
/*
http://www.mwsoft.jp/programming/nlp/mecab_cpp.html
for (; node; node = node->next) {
std::cout << "==========" << std::endl;
std::cout << "id : " << node->id << std::endl;
std::cout << "surface : " << node->surface << std::endl;
std::cout << "feature : " << node->feature << std::endl;
std::cout << "length : " << node->length << std::endl;
std::cout << "rlength : " << node->rlength << std::endl;
std::cout << "rcAttr : " << node->rcAttr << std::endl;
std::cout << "lcAttr : " << node->lcAttr << std::endl;
std::cout << "posid : " << node->posid << std::endl;
std::cout << "char_type : " << (int)node->char_type << std::endl;
std::cout << "stat : " << (int)node->stat << std::endl;
std::cout << "isbest : " << (int)node->isbest << std::endl;
std::cout << "alpha : " << node->alpha << std::endl;
std::cout << "beta : " << node->beta << std::endl;
std::cout << "prob : " << node->prob << std::endl;
std::cout << "wcost : " << node->wcost << std::endl;
std::cout << "cost : " << node->cost << std::endl;
}
==========
id : 0
surface : 昼寝する
feature : BOS/EOS,*,*,*,*,*,*,*,*
length : 0
rlength : 0
rcAttr : 0
lcAttr : 0
posid : 0
char_type : 0
stat : 2
isbest : 1
alpha : 0
beta : 0
prob : 0
wcost : 0
cost : 0
*/
func DumpNode(n *C.mecab_node_t) {
fmt.Printf("id: %d\n", int(n.id))
fmt.Printf("surface: %s\n", C.GoString(n.surface))
fmt.Printf("feature: %s\n", C.GoString(n.feature))
fmt.Printf("length: %d\n", int(n.length))
fmt.Printf("rlength: %d\n", int(n.rlength))
fmt.Printf("rcAttr: %d\n", int(n.rcAttr))
fmt.Printf("lcAttr: %d\n", int(n.lcAttr))
fmt.Printf("posid: %d\n", int(n.posid))
fmt.Printf("char_type: %d\n", int(n.char_type))
fmt.Printf("stat: %d\n", int(n.stat))
fmt.Printf("isbest: %d\n", int(n.isbest))
fmt.Printf("alpha: %d\n", int(n.alpha))
fmt.Printf("beta: %d\n", int(n.beta))
fmt.Printf("wcost: %d\n", int(n.wcost))
fmt.Printf("cost: %d\n", int(n.cost))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment