$Id: libmecab.html 65 2007-01-30 00:52:53Z taku-ku $;
C ライブラリは以下の関数を提供しています.
mecab_t *mecab_new (int argc, char **argv)
mecab_t *mecab_new2 (const char *arg)
const char *mecab_version()
const char *mecab_strerror (mecab_t* m)
const char *mecab_sparse_tostr (mecab_t *m, const char
*str)
const char *mecab_sparse_tostr2 (mecab_t *m, const char *str,
size_t len)
char *mecab_sparse_tostr3 (mecab_t *m, const char
*istr,size_t ilen char *ostr, size_t olen)
const char *mecab_nbest_sparse_tostr
(mecab_t *m, size_t N, const char *str)
const char *mecab_nbest_sparse_tostr2
(mecab_t *m, size_t N, const char *str, size_t len)
char *mecab_nbest_sparse_tostr3
(mecab_t *m, size_t N, const char *str, size_t len, char *ostr, size_t olen)
int mecab_nbest_init
(mecab_t* m, const char* str);
int mecab_nbest_init2
(mecab_t* m, const char* str, len);
const char *mecab_nbest_next_tostr
(mecab_t* m)
char *mecab_nbest_next_tostr2
(mecab_t *m , char *ostr, size_t olen)
void mecab_destroy(mecab_t *m)
形態素情報を取り出すには,以下の mecab_node_t 構造体と mecab_sparse_tonode 関数を使います
#define MECAB_NOR_NODE 0 #define MECAB_UNK_NODE 1 #define MECAB_BOS_NODE 2 #define MECAB_EOS_NODE 3 struct mecab_node_t { struct mecab_node_t *prev; // 一つ前の形態素へのポインタ struct mecab_node_t *next; // 一つ先の形態素へのポインタ struct mecab_node_t *enext; // 同じ位置で終わる形態素へのポインタ struct mecab_node_t *bnext; // 同じ開始位置で始まる形態素へのポインタ char *surface; // 形態素の文字列情報 // NULL terminateされていません. 文字列として取り出すには // strncpy(buf, node->feature, node->length) とする必要があります char *feature; // CSV で表記された素性情報 unsigned int length; // 形態素の長さ unsigned int rlength; // 形態素の長さ(先頭のスペースを含む) unsigned int id; // 形態素に付与される ユニークID unsigned short rcAttr; // 右文脈 id unsigned short lcAttr; // 左文脈 id unsigned short posid; // 形態素 ID (未使用) unsigned char char_type; // 文字種情報 unsigned char stat; // 形態素の種類: 以下のマクロの値 // #define MECAB_NOR_NODE 0 // #define MECAB_UNK_NODE 1 // #define MECAB_BOS_NODE 2 // #define MECAB_EOS_NODE 3 unsigned char isbest; // ベスト解の場合 1, それ以外 0 float alpha; // forward backward の foward log 確率 float beta; // forward backward の backward log 確率 float prob; // 周辺確率 // alpha, beta, prob は -l 2 オプションを指定した時に定義されます short wcost; // 単語生起コスト long cost; // 累積コスト };
mecab_node_t *mecab_sparse_tonode (mecab_t *m, const char *str)
mecab_node_t *mecab_sparse_tonode2 (mecab_t *m, const char *str,
size_t len)
mecab_node_t *mecab_next_tonode
(mecab_t* m)
example/example.c
#include <mecab.h> #include <stdio.h> #define CHECK(eval) if (! eval) { \ fprintf (stderr, "Exception:%s\n", mecab_strerror (mecab)); \ mecab_destroy(mecab); \ return -1; } int main (int argc, char **argv) { char input[1024] = "太郎は次郎が持っている本を花子に渡した。"; mecab_t *mecab; mecab_node_t *node; const char *result; int i; mecab = mecab_new (argc, argv); CHECK(mecab); result = mecab_sparse_tostr(mecab, input); CHECK(result) printf ("INPUT: %s\n", input); printf ("RESULT:\n%s", result); result = mecab_nbest_sparse_tostr (mecab, 3, input); CHECK(result); fprintf (stdout, "NBEST:\n%s", result); CHECK(mecab_nbest_init(mecab, input)); for (i = 0; i < 3; ++i) { printf ("%d:\n%s", i, mecab_nbest_next_tostr (mecab)); } node = mecab_sparse_tonode(mecab, input); CHECK(node); for (; node; node = node->next) { fwrite (node->surface, sizeof(char), node->length, stdout); printf("\t%s\n", node->feature); } node = mecab_sparse_tonode(mecab, input); CHECK(node); for (; node; node = node->next) { printf("%d ", node->id); if (node->stat == MECAB_BOS_NODE) printf("BOS"); else if (node->stat == MECAB_EOS_NODE) printf("EOS"); else fwrite (node->surface, sizeof(char), node->length, stdout); printf(" %s %d %d %d %d %d %d %d %d %f %f %f %d\n", node->feature, (int)(node->surface - input), (int)(node->surface - input + node->length), node->rcAttr, node->lcAttr, node->posid, (int)node->char_type, (int)node->stat, (int)node->isbest, node->alpha, node->beta, node->prob, node->cost); } mecab_destroy(mecab); return 0; }
以下が C++ API です. 基本的に C のインタフェイスと同一ですが,
といった違いがあります.
namespace MeCab { typedef struct mecab_node_t Node; class Tagger { public: virtual const char* parse(const char*, size_t, char*, size_t) = 0; virtual const char* parse(const char*, size_t = 0) = 0; virtual Node* parseToNode(const char*, size_t = 0) = 0; virtual const char* parseNBest(size_t, const char*, size_t = 0) = 0; virtual bool parseNBestInit(const char*, size_t = 0) = 0; virtual Node* nextNode() = 0; virtual const char* next() = 0; virtual const char* formatNode(Node *) = 0; virtual const char* next(char*, size_t) = 0; virtual const char* parseNBest(size_t, const char*, size_t, char *, size_t) = 0; virtual const char* formatNode(Node *, char *, size_t) = 0; virtual const char* what() = 0; virtual ~Tagger() {}; static const char *version(); static Tagger* create(int, char**); static Tagger* create(const char*); }; /* factory method */ Tagger *createTagger (int, char**); Tagger *createTagger (const char*); const char* getTaggerError (); }
#include <iostream> #include <mecab.h> #define CHECK(eval) if (! eval) { \ const char *e = tagger ? tagger->what() : MeCab::getTaggerError(); \ std::cerr << "Exception:" << e << std::endl; \ delete tagger; \ return -1; } int main (int argc, char **argv) { char input[1024] = "太郎は次郎が持っている本を花子に渡した。"; MeCab::Tagger *tagger = MeCab::createTagger (argc, argv); CHECK(tagger); const char *result = tagger->parse(input); CHECK(result); std::cout << "INPUT: " << input << std::endl; std::cout << "RESULT: " << result << std::endl; result = tagger->parseNBest(3, input); CHECK(result); std::cout << "NBEST: " << std::endl << result; CHECK(tagger->parseNBestInit(input)); for (int i = 0; i < 3; ++i) { std::cout << i << ":" << std::endl << tagger->next(); } MeCab::Node* node = tagger->parseToNode(input); CHECK(node); for (; node; node = node->next) { std::cout.write(node->surface, node->length); } node = tagger->parseToNode(input); CHECK(node); for (; node; node = node->next) { std::cout << node->id << ' '; if (node->stat == MECAB_BOS_NODE) std::cout << "BOS"; else if (node->stat == MECAB_EOS_NODE) std::cout << "EOS"; else std::cout.write (node->surface, node->length); std::cout << ' ' << node->feature << ' ' << (int)(node->surface - input) << ' ' << (int)(node->surface - input + node->length) << ' ' << node->rcAttr << ' ' << node->lcAttr << ' ' << node->posid << ' ' << (int)node->char_type << ' ' << (int)node->stat << ' ' << (int)node->isbest << ' ' << node->alpha << ' ' << node->beta << ' ' << node->prob << ' ' << node->cost << std::endl; } delete tagger; return 0; }
% cc -O2 `mecab-config --cflags` example.c -o example \ `mecab-config --libs`
まず, コンパイル作業を行うディレクトリに include\mecab.h, bin\libmecab.dll lib\libmecab.lib をコピーします. この後の作業は, 使用するコンパイラによって微妙に変わります.
% gcc -DDLL_IMPORT -I. example.c -o example.exe libmecab.dll
% cl -DDLL_IMPORT -I. example.c libmecab.lib
MeCab は,マルチスレッド環境で使用することが可能です. 1つのスレッドに 1インスタンス(mecab_t *)を割り当てる場合はスレッドセーフです. さらに, 同じ辞書を使い続ける限り,辞書を保持しているリソースは 再利用されるため, 複数のインスタンスを作成しても多くのメモリを使用することはありません.
一つのインスタンスを複数のスレッドから使う場合は適当に排他制御する必要があります. ただし, パフォーマンスが悪いのでお勧めできません.
$Id: libmecab.html 65 2007-01-30 00:52:53Z taku-ku $;