$Id: libmecab.html 161 2008-02-03 09:58:46Z 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;        // 累積コスト
};
const mecab_node_t *mecab_sparse_tonode (mecab_t *m, const char *str)const mecab_node_t *mecab_sparse_tonode2 (mecab_t *m, const char *str,
size_t len)const mecab_node_t *mecab_next_tonode
(mecab_t* m)
    辞書の情報を取り出すには mecab_dictionary_t 構造体と mecab_dictionary_info() 関数を使います
#define MECAB_USR_DIC   1
#define MECAB_SYS_DIC   0
#define MECAB_UNK_DIC   2
struct mecab_dictionary_info_t {
  const char                     *filename;  // 辞書のファイル名
  const char                     *charset;   // 辞書の文字コード
  unsigned int                    size;      // 単語数
  int                             type;      // 辞書のタイプ
                                             // MECAB_(USR|SYS|UNK)_DIC のいずれか
  unsigned int                    lsize;     // 左文脈 ID のサイズ
  unsigned int                    rsize;     // 右文脈 ID のサイズ
  unsigned short                  version;   // バージョン
  struct mecab_dictionary_info_t *next;   // 次の辞書へのポインタ
};
const mecab_dictionary_info_t *mecab_dictionary_info(mecab_t *m)以下のAPIで解析のパラメータや条件を変更することができます。
int mecab_get_partial(mecab_t *m)void mecab_set_partial(mecab_t *m)float mecab_get_theta(mecab_t *m)void mecab_set_theta(mecab_t *m, float theta)int mecab_get_lattice_level(mecab_t *m)void mecab_set_lattice_level(mecab_t *m, int lattice_level)int mecab_get_all_morphs(mecab_t *m)void mecab_set_all_morphs(mecab_t *m, int all_mophrs)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;
  typedef struct mecab_dictionary_info_t     DictionaryInfo;
  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 bool  partial() const                             = 0;
    virtual void  set_partial(bool partial)                   = 0;
    virtual float theta() const                               = 0;
    virtual void  set_theta(float theta)                      = 0;
    virtual int   lattice_level() const                       = 0;
    virtual void  set_lattice_level(int level)                = 0;
    virtual bool  all_morphs() const                          = 0;
    virtual void  set_all_morphs(bool all_morphs)             = 0;
    virtual const char* what() = 0;
    virtual const DictionaryInfo* dictionary_info() const = 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 161 2008-02-03 09:58:46Z taku-ku $;