- - PR -
Java(JNI)でCaboChaを使う方法
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-09-17 15:30
Javaで係り受け解析器CaboChaを動かす方法を探しています。
CaboChaはC言語で動かすことが出来るので、JNIを用いて試みたのですが、 実行途中にエラーが出て止まってしまいます。 主なエラーメッセージは以下の通りです。 An unrecoverable stack overflow has occurred. An unexpected exception has been detected in native code outside the VM. Unexpected Signal : EXCEPTION_STACK_OVERFLOW occurred at PC=0x66E57153 Function=cha_tok_is_jisx0208_latin+0xC4C3 Library=C:\JavaHello\cabocha_c\libchasen.dll JavaでCaboChaを動かす方法を御存知の方、御教授いただければ幸いです。 また、C言語のmain関数(コマンドライン引数を使用)をそのままJNIを使ってJava上で動かす方法でも構いません。 何卒よろしくお願いします。 ----------- Windows XP Borland C++ コンパイラ5.5 CaboCha-0.51 j2sdk1.4.1_02 ------------ | ||||||||
|
投稿日時: 2004-09-17 21:21
unibon です。こんにちわ。
CaboCha とかはぜんぜん知らないのですが、エラーメッセージで検索して、リンクをたどっていくと、 http://www.google.co.jp/search?num=50&hl=ja&ie=UTF-8&c2coff=1&q=An+unrecoverable+stack+overflow+has+occurred&btnG=Google+%E6%A4%9C%E7%B4%A2&lr= ↓ http://www.experts-exchange.com/Programming/Programming_Languages/Q_20864382.html ↓ http://forum.java.sun.com/thread.jsp?forum=37&thread=486077&start=0&range=15#2279387 に行き、そのへんのキーワードから、検索すると、たとえばですが、 http://edocs.beasys.co.jp/e-docs/wls/docs70/faq/java.html みたいなところにたどりつきました。 -ss のオプションあたりで native なスタックサイズを指定できるのかもしれません。 http://java.sun.com/j2se/1.4/ja/docs/ja/tooldocs/win32/java.html には書いてありませんが、無視はされないような感じもします。 | ||||||||
|
投稿日時: 2004-09-17 23:26
unibonさん:
ありがとうございます。 まず教えていただいたリンクを読んでみて試せるところは試してみます。 改善できたら報告させていただきます。 | ||||||||
|
投稿日時: 2004-09-21 15:46
むぅいしです。
unibonさんに教えて頂いたページの方法を試してみました。 http://forum.java.sun.com/thread.jsp?forum=37&thread=418834 を見ると、-Xms -Xms -Xssの組み合わせを使うと良いとかいてありましたので、 C:\JavaHello\cabocha_c>java -ms10m -mx100m -oss2048k -ss2048k ExampleJNI と全てをデフォルトより数倍大きくして実行してみましたが、以前と変わらないエラーメッセージが出てきました。 いろいろ調べてみた結果、Cのコードの方で、45行目をコンパイルせずに実行すると、 とりあえず、止まらずに最後まで動きました。 以下はCのソースコードです。 #include <jni.h> #include "ExampleJNI.h" #include <stdio.h> #ifdef _WIN32 #include <windows.h> typedef void* (WINAPI *FPINIT2) (char *); typedef char* (WINAPI *FPERR) (void*); typedef char* (WINAPI *FPPARSE) (void*, char*); typedef void (WINAPI *FPDEL) (void *); #endif JNIEXPORT void JNICALL Java_ExampleJNI_sayHelloWorld (JNIEnv *env, jobject obj){ #ifdef _WIN32 char p[] = "太郎は次郎が持っている本を花子に渡した。"; char* fpparse_temp; HINSTANCE hLib = LoadLibrary ("libcabocha.dll"); HINSTANCE hLib2 = LoadLibrary ("libchasen.dll"); if (hLib) { fprintf(stderr, "libchasen loaded.\n"); FreeLibrary(hLib2); } else { fprintf(stderr, "Error\n"); } if (hLib) { FPINIT2 fpInit2 = (FPINIT2) GetProcAddress(hLib, "cabocha_new2"); FPERR fpErr = (FPERR) GetProcAddress(hLib, "cabocha_strerror"); FPPARSE fpParse = (FPPARSE) GetProcAddress(hLib, "cabocha_sparse_tostr"); FPDEL fpDel = (FPDEL) GetProcAddress(hLib, "cabocha_destroy"); if (fpInit2 && fpErr && fpParse && fpDel) { void *c = (void *)(*fpInit2)(""); if (!c) { fprintf (stderr, "Exception %s\n", (*fpErr)(c)); FreeLibrary(hLib); //return -1; } printf ("INPUT: %s\n", p); // ↓■■■45行目 printf ("RESULT:\n%s", (char *)(*fpParse)(c, p)); (*fpDel)(c); } FreeLibrary(hLib); } #endif //return 0; } ちなみに、Javaのコードは以下のとおりです。 public class ExampleJNI { static { // ライブラリをロードします System.loadLibrary("example-win32-dll"); } // ネイティブメソッドを宣言します //public native void sayHelloWorld(int args, String[] argv); public native void sayHelloWorld(); public static void main (String[] args) { ExampleJNI hello = new ExampleJNI(); // メソッドを実行して表示します hello.sayHelloWorld(); } } 些細なことでも結構ですので、何かヒントになるようなことがありましたら、 ぜひともご教授ください。 よろしくお願いしたします。 | ||||||||
|
投稿日時: 2004-09-21 16:16
unibon です。こんにちわ。
おそらく、正常にスタックを使って足りなくなっているのではなく、プログラムの間違いでスタック領域を壊してしまっているのだろうと思います。 関数ポインタの使い方が怪しそうですが、ちょっとすぐには分からないです。 もしかしたら、
のほうが良いのかもしれません。 http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/Runtime.html#exec(java.lang.String[]) で EXE を起動することはできますが、こんどは情報のやりとりをどうするか(標準入出力を使う等)で悩むかもしれまん。ただ、もちろんスタック関係のエラーは出ようがありませんが。 | ||||||||
|
投稿日時: 2004-09-21 17:25
むぅいしです。
unibonさん: 早速ご返答頂き、本当にありがとうございます。 教えて頂いたリンクと、 http://www.hellohiro.com/command.htm を参照してJavaのソースを作り、Javaを実行してみたところ、 EXEを無事に動かすことができました。オプションも問題なく反映されました。 これから自分が作ろうとしているプログラムは、 テキストファイルを入力して、その出力結果をJavaの方で使うという流れなので、 Cのコードを書き換えることで、対応できるような気がしています。 スタックのエラーのほうは、時間の許す限り、もう少し調べてみたいと思います。 きっと、main関数がもともと用意されている場合は、execメソッドで動かす方法が、 一番無難なやり方なのかな、とも思えてきましたが。 また進展がありましたら、ご報告させていただきます。 | ||||||||
|
投稿日時: 2004-09-21 22:48
atmartitでCaboChaの質問が出てくるとは思いませんでした。 知ってるかもしれませんがCaboChaはSwigというCやC++などでできたライブラリをperl/rubyなどのスクリプト言語から呼び出せるにする機構を利用しています。 でこのSwigはJavaにも対応しているはずなのでSwigを使ったほうが楽なのではないでしょうか? (自分で使ったことはないですがWindowsにも対応してるはず) ただ、perl/ruby/pythonバインディングがすでにあるのにJavaだけないっていうのはなんか理由があるかもしれないので、 作者にそこらへんのところを聞いといたほうがいいとは思いますが。 | ||||||||
|
投稿日時: 2004-09-22 16:03
むぅいしです。
とんびさん: アドバイスありがとうございます。 Swigというものがあることを、昨日CaboChaの作者の方の日記を見て初めて知りました。 なぜJavaのバインディングがないのか、作者の方に理由だけでも聞いてみたいと思います。 理由が分かりましたら、またご報告させていただきます。 |
1