情報を聞いたので、実際に深追いしてみました。
いとも簡単に /usr/lib/libmecab* , /usr/include/mecab.h と /usr/lib/mecab/dic/apple/{ja,tc,sc} というディレクトリを発見しました。ts, sc は traditional/simplified Chinese (繁体字/簡体字) の略で、中国語の辞書だと推察されます。辞書のディレクトリはさらに dic/apple/ja/{LE,BE} という風に、エンディアンごとに分かれています。MeCabの辞書はエンディアン依存なので、こうするしかないのかもしれません。
さて、この辞書を使って、UTF8の文字列を流し込んでみたのですが、うまいこと解析してくれません。MeCabのバイナリ辞書形式には文字コードの情報が文字列で埋め込まれているので、その部分を
バイナリエディタで見ると、UTF-16LE となっています。どうやら入出力を UTF-16LE にすれば形態素解析ができそうです。
確認のためのコード
#include <mecab.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
char *iconv_convert_helper(iconv_t ic, const char *input, size_t ilen,
size_t *length) {
size_t olen = ilen * 4;
char *result = (char *)malloc(olen);
char *ibuf = (char *)input;
char *obuf_org = result;
char *obuf = result;
size_t olen_org = olen;
memset(result, 0, olen);
if (ic == (iconv_t)(-1)) {
exit(-1);
}
while (ilen != 0) {
if (iconv(ic, (char **)(&ibuf), &ilen, &obuf, &olen) == (size_t)(-1)) {
fprintf(stderr, "error in iconv\n");
free(result);
return NULL;
}
}
*length = olen_org - olen;
obuf_org[*length] = '\0';
iconv_close(ic);
return result;
}
char *utf8_to_utf16(const char *input, size_t ilen, size_t *olen) {
iconv_t ic = iconv_open("UTF-16LE", "UTF-8");
return iconv_convert_helper(ic, input, ilen, olen);
}
char *utf16_to_utf8(const char *input, size_t ilen, size_t *olen) {
iconv_t ic = iconv_open("UTF-8", "UTF-16LE");
return iconv_convert_helper(ic, input, ilen, olen);
}
int main (int argc, char **argv) {
mecab_t *mecab;
const mecab_node_t *node;
char buf[8192];
char *buf2;
mecab = mecab_new2("-d /usr/lib/mecab/dic/apple/ja/LE");
if (mecab == NULL) {
fprintf(stderr, "error in mecab_new2: %s\n", mecab_strerror(NULL));
return -1;
}
while (fgets(buf, sizeof(buf), stdin)) {
buf[strlen(buf) - 1] = '\0';
size_t olen = 0;
buf2 = utf8_to_utf16(buf, strlen(buf), &olen);
node = mecab_sparse_tonode2(mecab, buf2, olen);
if (node == NULL) {
fprintf(stderr, "error\n");
exit(-1);
}
node = node->next;
for (; node->next != NULL; node = node->next) {
char *r = utf16_to_utf8(node->surface, node->length, &olen);
printf("%s|", r);
free(r);
}
free(buf2);
printf("\n");
}
mecab_destroy(mecab);
return 0;
}
% gcc test.c -lmecab -liconv
% echo 私の名前は中野です | ./a.out
私|の|名前|は|中野|です|
うひょー。分かち書きできます。品詞情報もあるみたいですが、Spotlight ではほとんど使われないようなので、一文字の品詞に省略されています。
]]>