2011/03/26

[java]cygwinでのJNIがうまくいかん

2回目にしてよくわからん。。。

package com.jnitest;

class Jni2 {
        public static void main(String[] args) {
                System.out.println("Hello");
                System.out.println(helloString());
        }
        
        static {
                System.loadLibrary("jnihello");
        }
        public static native String helloString();
}

こんなのだ。

これをコンパイル。

$ javac com/jnitest/Jni2.java

そして、javah

$ javah com.jnitest.Jni2

com_jnitest_Jni2.hというヘッダファイルができる。
これを使ってCソースを書く。

#include "com_jnitest_Jni2.h"

JNIEXPORT jstring JNICALL Java_com_jnitest_Jni2_helloString
  (JNIEnv *env, jclass clazz)
{
        return "Hello !";
}

まあこんなもんだろう。

これをコンパイル。参考はここ

gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -shared -o jnihello.dll com_jnitest_Jni2.c

jnitest.dllができるので、パスが通ったところにコピー。
そして実行。

$ java com.jnitest.Jni2
Aborted

Abortか・・・。


DLLがないと、loadLibrary()が例外を出す。
だから、DLLが見つからないわけではない。

helloString()を呼び出す行をなくしても変わらないので、関数でエラーになっているわけではない。
ということは、DLLの読み込み付近でJava以外でのエラーが発生していることになる。

幸いなことに、むかーしJavaを勉強したときのJNI DLLが残っていた。
StdAfx、なんてのがあるから、Visutl Studio6で作ったのだろう。
これが読み込めるなら、jnihello.dllに問題がある。。。読み込めた。
というわけで、jnihello.dll自体に何かありそうだ。

今使っているJavaは、1.6.0_24である。


MINGWのコンパイル方法と違うのは、-Iしてないところくらいか。
コンパイルできてるから、インクルードパスの指定はいらんと思ってるけど、まあやっておくか。

・・・コンパイルエラーが出た。
ということは、デフォルトの参照先ではだめということか!
うん、書いてあることはちゃんと意味があるのだな。

コンパイルエラーは、jlongがうんたらかんたら。
include/win32/jni_md.hのところだ。
ここで__int64というのがあるが、これがいかんのだろう。long longかな。

そうすると、今度は「互換のない型だ」といわれた。
const char*を返しているけど、要求されているのはjstring型か。
どうせtypedefしなおしただけなんじゃないの? jni.hを見てみると、

class _jstring : public _jobject {};
typedef _jstring *jstring;

違うやん。
変換が必要ということか。
しかもコピー返しではなくアドレス返しか。
ヒープに取ってやらんといかんことになるが、どうやって解放すればいいんだろう?
JavaVMがやってれるのか?

NewStringUTF()は、なんか解放処理みたいなことはしなくてもよさそうに見える。
GetStringChars()したらReleaseStringChars()し、GetStringUTFChars()したらReleaseStringUTFChars()しないといかんが、それ以外の文字列操作は気にしなくてよさそうだ。

#include "com_jnitest_Jni2.h"
JNIEXPORT jstring JNICALL Java_com_jnitest_Jni2_helloString
(JNIEnv *env, jclass clazz)
{
jstring js = (*env)->NewStringUTF(env, "Hello");
return js;
}

$ gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I/java/include -I/java/include/win32 -shared -o jnihello.dll com_jnitest_Jni2.c

実行させてみよう!

$ java com.jnitest.Jni2
Aborted

Abortか・・・。


もしかしたら、パスがわからなくなっているとか?

System.load("e:/Prog/Java/JniStudy/2/jnihello.dll");

直指定してもだめか。。。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。