# MeCab ライブラリ

$Id: libmecab.html,v 1.16 2003/07/03 11:54:57 taku-ku Exp $;

MeCabには, C/C++ 共用のライブラリ (mecab.h, libmecab.so/limecab.dll) があります.

## C ライブラリ仕様

C ライブラリは以下の関数を提供しています.

`mecab_t *mecab_new (int argc, char **argv)`
  mecab のインスタンスを生成します.
  引数には, C 言語の, main 関数で使用される argc, argv スタイルの引数を与えます.
  この引数は, mecab コマンドと同じ方法で処理されます.
  成功すれば, mecab_t 型のポインタが返ってきます. このポインタを通して解析 を行います. 失敗すれば NULL が返ってきます.
`mecab_t *mecab_new2 (char *arg)`
  mecab のインスタンスを生成します.
  引数には, 一つの文字列として表現したパラメータを与えます.
  成功すれば, mecab_t 型のポインタが返ってきます. このポインタを通して解析を行います.
`char *mecab_strerror (mecab_t* m)`
  エラーの内容を文字列として取得します. mecab_sparse_tostr 等で, NULL が返ってきた場合に, mecab_strerror を呼ぶことで, エラーの内容を取得できます. mecab_new,mecab_new2 のエラーは, m を NULL と指定してください.
`char *mecab_sparse_tostr (mecab_t *m, char *str)`
  解析を行います. 引数には, mecab_new で得られた mecab_t 型のポインタと,
  解析したい文を char 型のポインタ文字列として与えます.
  成功すれば, 解析後の結果が char 型のポインタとして返り, 失敗すれば, NULL が返ってきます
  戻り値のポインタが指すメモリ領域は, 呼び出し側で管理する必要はありませんが,
  mecab_sparse_tostr を呼ぶ度に上書きされます.
  また, mecab_destroy を呼ぶと解放されます.
`char *mecab_sparse_tostr2 (mecab_t *m, char *str, unsigned int len)`
  mecab_sparse_tostr とほぼ同じですが, len にて, 解析する文の長さを指定できます.
`char *mecab_sparse_tostr3 (mecab_t *m, char *istr,unsigned int ilen char *ostr,unsigned int olen)`
  mecab_sparse_tostr2 に加え, 出力用の バッファ領域 (ostr), 及びその長さ (olen) を指定できます. ostr の領域の管理は, 呼び出し側が行います. 成功すれば, 解析後の結果が char 型のポインタとして返ってきます. これは, ostr と同じになります. もし, 解析結果の長さが olen 以上になった場合は, 解析失敗とみなし, NULL を返します.
`char *mecab_nbest_sparse_tostr (mecab_t *m, unsigned int N, char *str)`
  mecab_sparse_tostr () の N-Best 解出力 version です. N にて解析結果の個 数を指定します. また, N-Best の機能を使う場合は, 必ず mecab_new にて -a オプションを指定する必要があります. デフォルトは, -a 無しとなっており, 最適解のパスのみを作ります. -a オプションを指定することで, すべてのパス (ラティス) を構築します.
`char *mecab_nbest_sparse_tostr2 (mecab_t *m, unsigned int N, char *str, unsigned int len)`
  mecab_sparse_tostr2 () の N-Best 解出力 version です. N にて解析結果の個 数を指定します.
`char *mecab_nbest_sparse_tostr3 (mecab_t *m, unsigned int N, char *str, unsigned int len, char *ostr, unsigned int olen)`
  mecab_sparse_tostr3 () の N-Best 解出力 version です. N にて解析結果の個 数を指定します.
`int mecab_nbest_init (mecab_t* m, char* str);`
  解析結果を, 確からしいものから順番に取得する場合にこの関数で初期化を行い ます. 解析したい文を str に指定します. 初期化に成功すると 1 を, 失敗する と 0 を返します. 失敗の原因は, mecab_strerror で取得できます.
`int mecab_nbest_init2 (mecab_t* m, char* str, len);`
  mecab_nbest_init () とほぼ同じですが, len にて文の長さを指定できます.
`char *mecab_next_tostr (mecab_t* m)`
  mecab_nbest_init() の後, この関数を順次呼ぶことで, 確からしい解析結果 を, 順番に取得できます. 失敗すると (これ以上の解が存在しない場合) NULL を返します. 失敗の原因は, mecab_strerror で取得できます.
`char *mecab_next_tostr2 (mecab_t *m , char *ostr, unsigned int olen)`
  mecab_nbest_tostr() とほぼ同じですが, ostr, olen にて出力用のバッファを 指定できます. 失敗すると (これ以上の解が存在しない場合) NULL を返します. また, 出力バッファが溢れた場合も NULL を返します. 失敗の原因は, mecab_strerror で取得できます.
`int mecab_lock (mecab_t *m)`
  m にて指定されるインスタンスの動作を mutex を用い 排他的に lock します. マルチスレッド環境にて インスタンス m を複数のスレッドから用いる場合は, lock が必要です.
`int mecab_unlock (mecab_t *m)`
  m にて指定されるインスタンスの動作の lock を解除します.
`void mecab_destroy(mecab_t *m)`
  mecab_t 型のポインタを解放します.

## C サンプル

example/example.c

    #include <mecab.h>
    #include <stdio.h>

    int main (int argc, char **argv)
    {
       mecab_t *c;
       char p[1024] = "太郎は次郎が持っている本を花子に渡した。";
       char *r;
       int i;

       c = mecab_new (argc, argv);
       if (c == NULL) {
          fprintf (stderr, "Exception:%s\n", mecab_strerror (c));
          return -1;
       }

       r = mecab_sparse_tostr(c, p);

       if (r == NULL) {
          fprintf (stderr, "Exception:%s\n", mecab_strerror (c));
          mecab_destroy(c);
          return -1;
       }

       printf ("INPUT: %s\n", p);
       printf ("RESULT:\n%s", r);

       r = mecab_nbest_sparse_tostr (c, 10, p);

       if (r == NULL) {
          fprintf (stderr, "Exception: [%s]\n", mecab_strerror (c));
          return -1;
       }

       fprintf (stdout, "NBEST: %s", r);

       if (! mecab_nbest_init (c, p)) {
          fprintf (stderr, "Exception: [%s]\n", mecab_strerror (c));
          return -1;
       };

       for (i = 0; i < 10; ++i) {
          printf ("%d: %s", i, mecab_nbest_next_tostr (c));
       }

       mecab_destroy(c);

       return 0;
    }

## C++ ライブラリ仕様

C++ ライブラリは, シンボルの解決がコンパイラの実装依存になっているため, すべてのケースで正しくリンクできるとは限りません. mecab をコンパイルし た環境と同一環境で API を利用する場合は問題ないと思います. example/example2.cpp に具体例を示していますので, そちらを参照ください. C のライブラリは, C++ API を薄く wrap したものにすぎません.

## コンパイル方法

- UNIX の場合

      % cc -O2 `mecab-config --cflags` example.c -o example \
               `mecab-config --libs`

- Windows の場合

  まず, コンパイル作業を行うディレクトリに include\mecab.h, bin\libmecab.dll lib\libmecab.lib をコピーします.
  この後の作業は, 使用するコンパイラによって微妙に変わります.

  cygwin/mingw 環境の場合

      % gcc -DDLL_IMPORT -I. example.c -o example.exe libmecab.dll

  Visual Studio .NET C++の場合

      % cl -DDLL_IMPORT -I. example.c libmecab.lib

  BCC32 環境の場合

      インポートライブラリの作成
      % implib.exe /a /f libmecab.lib libmecab.dll
      コンパイル
      % bcc32 -DDLL_IMPORT -I. example.c libmecab.lib

  さらに, 以下例ように, libmecab.dll と動的 にリンクすることも可能です.
  この場合は, インポートライブラリを作成する必要はありません.

      #include <stdio.h>
      #include <windows.h>

      typedef void* (WINAPI *FPINIT)  (int, char **);
      typedef char* (WINAPI *FPERR)   (void*);
      typedef char* (WINAPI *FPPARSE) (void*, char*);
      typedef void  (WINAPI *FPDEL)   (void *);

      int main (int argc, char **argv)
      {
         char p[] = "太郎は次郎が持っている本を花子に渡した。";
         HINSTANCE hLib = LoadLibrary("libmecab.dll");

         if (hLib) {
            FPINIT  fpInit  = (FPINIT)  GetProcAddress(hLib, "mecab_new");
            FPERR   fpErr   = (FPERR)   GetProcAddress(hLib, "mecab_strerror");
            FPPARSE fpParse = (FPPARSE) GetProcAddress(hLib, "mecab_sparse_tostr");
            FPDEL   fpDel   = (FPDEL)   GetProcAddress(hLib, "mecab_destroy");

            if (fpInit && fpErr && fpParse && fpDel) {
               void *c = (void *)(*fpInit)(argc, argv);
               if (!c) {
                  fprintf (stderr, "Exception %s\n", (*fpErr)(c));
                  FreeLibrary(hLib);
                  return -1;
               }

               printf ("INPUT: %s\n", p);
               printf ("RESULT:\n%s", (char *)(*fpParse)(c, p));
               (*fpDel)(c);
            }
            FreeLibrary(hLib);
         }

         return 0;
      }

## マルチスレッドについて

MeCab は, マルチスレッド環境で使用することが可能です. 使い方は, 以下の2つの方法があります.

### 1インスタンス = 1スレッドの場合

1つのスレッドに 1インスタンスを割りあてる場合は, ユーザがとりたてて必要することはございません. 辞書は mmap (MapViewOfFile) を用いて, OS の仮想メモリ上に 割りあてられるため, 複数のインスタンスを作成しても, 多くのメモリを使用することは ありません.

### 1インスタンスを複数のスレッドからアクセスする場合

この場合は, 同期をとる必要があります. 具体的には, mecab_lock にて 1つのスレッドが使用権を取得し, 解析後に mecab_unlock を使い使用権を 開放します. さらに, mecab_sparse_tostr () が返すメモリ領域は, 各インスタンスが管理し ています. そのため, unlock は, mecab_sparse_tostr () の結果を アプリケーション側で処理した 後に 行なう必要があります. ただし, mecab_sparse_tostr3 にて, バッファを指定した場合は その限りではありません.

マルチスレッド (pthread) の場合の例を example/example-thread.c example/example-thread2.c に示します.

$Id: libmecab.html,v 1.16 2003/07/03 11:54:57 taku-ku Exp $;