libchasen.so: undefined symbol: cerr

JavaからJNICaboChaを呼ぶと上記のエラーが出る。
以下、とりあえず状況の整理をしてみた。Linuxで検証したけど多分Windowsでも同じだと思う。

libchasen.soはlibstdc++.aがリンクされていないので、呼び出し元にリンクしておく必要がある。
ところで、AというプログラムがBというライブラリをロードして、BがCという別のライブラリをロードした状況では、Cが必要とするライブラリは(Bではなく)Aにリンクされていないといけない(らしい)。
さて、ここでA=java,B=libcabocha.so,C=libchasen.soとすると、libchasen.soが必要とするlibstdc++.aがJavaにリンクされていない(当然)ので、エラーになるわけだ。

参考リンク

ここまで分かって、じゃあどうすればいいかというとちょっと思い付かない。そもそもlibchasen.soにlibstdc++.aをリンクしてしまってもいいのか?

最後に、最小限のテストコードを載せておく。

  • test_a.c
#include <stdio.h>
#include <dlfcn.h>

typedef void (*FUNCPTR)();

int main(int argc, char *argv[])
{
  void *hLib = dlopen("libtest_b.so", RTLD_LAZY);
  if (hLib == NULL) {
    fprintf(stderr, __FILE__": Error: %s\n", dlerror());
  } else {
    FUNCPTR func;

    fprintf(stderr, __FILE__": Library loaded.\n");
    func = dlsym(hLib, "func");
    if (func) {
      (*func)();
    } else {
      fprintf(stderr, __FILE__": Error: %s\n", dlerror());
    }
    dlclose(hLib);
  }

  return 0;
}
  • test_b.c
#include <stdio.h>
#include <dlfcn.h>

void func()
{
  void *hLib = dlopen("libchasen.so", RTLD_LAZY);
  if (hLib == NULL) {
    fprintf(stderr, __FILE__": Error: %s\n", dlerror());
   } else {
    fprintf(stderr, __FILE__": Library loaded.\n");
    dlclose(hLib);
  }
}
% gcc -Wall test_a.c -o test_a -ldl
% gcc -Wall test_a.c -o test_a++ -ldl -lstdc++
% gcc -shared -Wall test_b.c -o libtest_b.so -ldl -lstdc++
  • 実行結果
% LD_LIBRARY_PATH=. ./test_a++
test_a.c: Library loaded.
test_b.c: Library loaded.
% LD_LIBRARY_PATH=. ./test_a
test_a.c: Library loaded.
test_b.c: Error: /usr/lib/libchasen.so: undefined symbol: cerr
%