MeCab 라이브러리

$Id: libmecab.html 65 2007-01-30 00:52:53Z taku-ku $;

C 라이브러리 사양

C 라이브러리는 이하의 함수를 제공하고 있습니다.

mecab_t *mecab_new (int argc, char **argv)
mecab 의 인스턴스를 생성합니다.
인수에는, C 언어의, main 함수로 사용된다 argc, argv 스타일의 인수를 줍니다.
이 인수는, mecab 커멘드 (와)과 같은 방법으로 처리됩니다.
성공하면, mecab_t 형태의 포인터가 되돌아 옵니다. 이 포인터를 통해 해석 (을)를 실시합니다. 실패하면 NULL 하지만 되돌아 옵니다.
mecab_t *mecab_new2 (const char *arg)
mecab 의 인스턴스를 생성합니다.
인수에는, 하나의 문자열로서 표현한 파라미터를 줍니다.
성공하면, mecab_t 형태의 포인터가 되돌아 옵니다. 이 포인터를 통하고 해석을 실시합니다.
const char *mecab_version()
mecab 의 version (을)를 문자열로서 취득합니다.
const char *mecab_strerror (mecab_t* m)
에러의 내용을 문자열로서 취득합니다. mecab_sparse_tostr 등으로, NULL 하지만 되돌아 왔을 경우에, mecab_strerror (을)를 부르는 것으로, 에러의 내용을 취득할 수 있습니다. mecab_new,mecab_new2 의 에러는, m (을)를 NULL (와)과 지정해 주세요.
const char *mecab_sparse_tostr (mecab_t *m, const char *str)
해석을 실시합니다. 인수에는, mecab_new 그리고 얻을 수 있었다 mecab_t 형태의 포인터와,
해석하고 싶은 문장을 char 형태의 포인터 문자열로서 줍니다.
성공하면, 해석 후의 결과가 char 형태의 포인터로서 돌아가, 실패하면, NULL 하지만 되돌아 옵니다
반환값의 포인터가 가리키는 메모리 영역은, 호출측에서 관리할 필요는 없습니다만,
mecab_sparse_tostr (을)를 부를 때마다 덧쓰기됩니다.
또, mecab_destroy (을)를 부르면 해방됩니다.
const char *mecab_sparse_tostr2 (mecab_t *m, const char *str, size_t len)
mecab_sparse_tostr (와)과 거의 같습니다만, len 에서, 해석하는 문장의 길이를 지정할 수 있습니다.
char *mecab_sparse_tostr3 (mecab_t *m, const char *istr,size_t ilen char *ostr, size_t olen)
mecab_sparse_tostr2 에 가세해, 출력용의 버퍼 영역 (ostr), 및 그 길이 (olen) (을)를 지정할 수 있습니다. ostr 의 영역의 관리는, 호출측이 실시합니다. 성공하면, 해석 후의 결과가 char 형태의 포인터로서 되돌아 옵니다. 이것은, ostr (와)과 같게 됩니다. 만약, 해석 결과의 길이가 olen 이상이 되었을 경우는, 해석 실패로 간주해, NULL (을)를 돌려줍니다.
const char *mecab_nbest_sparse_tostr (mecab_t *m, size_t N, const char *str)
mecab_sparse_tostr () 의 N-Best 해출력 version 입니다. N 에서 해석 결과의 개 수를 지정합니다. 또, N-Best 의 기능을 사용하는 경우는, 반드시 mecab_new 에서 -l 1 옵션을 지정할 필요가 있습니다.
const char *mecab_nbest_sparse_tostr2 (mecab_t *m, size_t N, const char *str, size_t len)
mecab_sparse_tostr2 () 의 N-Best 해출력 version 입니다. N 에서 해석 결과의 개 수를 지정합니다.
char *mecab_nbest_sparse_tostr3 (mecab_t *m, size_t N, const char *str, size_t len, char *ostr, size_t olen)
mecab_sparse_tostr3 () 의 N-Best 해출력 version 입니다. N 에서 해석 결과의 개 수를 지정합니다.
int mecab_nbest_init (mecab_t* m, const char* str);
해석 결과를, 확실한 것 같은 것으로부터 차례로 취득하는 경우에 이 함수로 초기화를 실시해 . 해석하고 싶은 문장을 str (으)로 지정합니다. 초기화에 성공하면 1 (을)를, 실패한다 (와)과 0 (을)를 돌려줍니다. 실패의 원인은, mecab_strerror 그리고 취득할 수 있습니다.
int mecab_nbest_init2 (mecab_t* m, const char* str, len);
mecab_nbest_init () (와)과 거의 같습니다만, len 에서 문장의 길이를 지정할 수 있습니다.
const char *mecab_nbest_next_tostr (mecab_t* m)
mecab_nbest_init() 의 후, 이 함수를 차례차례 부르는 것으로, 확실한 것 같은 해석 결과 (을)를, 차례로 취득할 수 있습니다. 실패하면 ( 더 이상의 해가 존재하지 않는 경우) NULL (을)를 돌려줍니다. 실패의 원인은, mecab_strerror 그리고 취득할 수 있습니다.
char *mecab_nbest_next_tostr2 (mecab_t *m , char *ostr, size_t olen)
mecab_nbest_tostr() (와)과 거의 같습니다만, ostr, olen 에서 출력용의 버퍼를 지정할 수 있습니다. 실패하면 ( 더 이상의 해가 존재하지 않는 경우) NULL (을)를 돌려줍니다. 또, 출력 버퍼가 흘러넘쳤을 경우도 NULL (을)를 돌려줍니다. 실패의 원인은, mecab_strerror 그리고 취득할 수 있습니다.
void mecab_destroy(mecab_t *m)
mecab_t 형태의 포인터를 해방합니다.

형태소 정보를 꺼내려면, 이하의 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_new 그리고 얻을 수 있었다 mecab_t 형태의 포인터와,
해석하고 싶은 문장을 char 형태의 포인터 문자열로서 줍니다.
성공하면, 문두의 형태소(mecab_node_t 형) 에의 포인터가 돌아가, 실패하면, NULL 하지만 되돌아 옵니다.
mecab_node_t (은)는 쌍방향 리스트가 되어 있기 때문에 next, prev (을)를 순서에 더듬는 일로 전형태소를 열거할 수 있습니다.
반환값의 포인터가 가리키는 메모리 영역은, 호출측에서 관리할 필요는 없습니다만,mecab_sparse_tonode (을)를 부를 때마다 덧쓰기됩니다.
또, mecab_destroy (을)를 부르면 해방됩니다.
mecab_node_t *mecab_sparse_tonode2 (mecab_t *m, const char *str, size_t len)
mecab_sparse_tonode (와)과 거의 같습니다만, len 에서, 해석하는 문장의 길이를 지정할 수 있습니다.
mecab_node_t *mecab_next_tonode (mecab_t* m)
mecab_next_tostr (와)과 거의 같습니다만, 문자열은 아니고 mecab_node_t 형태의 형태소 정보를 돌려줍니다.

C 샘플

example/example.c

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

#define CHECK(eval) if (! eval) { 
    fprintf (stderr, "Exception:%sn", 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: %sn", 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%sn", 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 %dn",
	   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++ 라이브러리 사양

이하가 C++ API 입니다. 기본적으로 C 의 interface와 동일합니다만,

그렇다고 하는 차이가 있습니다.

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 ();
}

C++ 샘플

#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;
}

컴파일 방법

multi-thread에 대해

MeCab 하, multi-thread 환경에서 사용하는 것이 가능합니다. 1 개의 스렛드에 1 인스턴스(mecab_t *) (을)를 할당하는 경우는 스렛드세이후입니다. 한층 더, 같은 사전을 계속 사용하는 한, 사전을 보관 유지하고 있는 자원은 재이용되기 위해, 복수의 인스턴스를 작성해도 많은 메모리를 사용할 것은 없습니다.

하나의 인스턴스를 복수의 스렛드로부터 사용하는 경우는 적당하게 배타 제어할 필요가 있습니다. 다만, 퍼포먼스가 나쁘기 때문에 추천할 수 없습니다.


$Id: libmecab.html 65 2007-01-30 00:52:53Z taku-ku $;