• 追加された行はこの色です。
  • 削除された行はこの色です。
  • Java/JNI へ行く。

[[Java]]

Javaのnativeメソッド

#contents

* 作成方法 [#x234af69]

なにはともれ、共有ライブラリを作成せなあかん

** cygwin-gcc [#y3d900c9]

いろいろ方法はあるんだろうけど、一番簡単そうなdefファイルを作ってやる方法。~
関数の数が多いと面倒だが。。

javahでヘッダーを作成したら、そのなかから関数の名前を取り出してきて
以下のようなファイル"hoge.def"を作成する。

 EXPORTS
  Java_NativeFunctions_initialize_1IMPL
  Java_NativeFunctions_terminate_1IMPL

という感じに、EXPORTSのあとに関数命を連ねる(戻り値とか引数は無視)

で、ソースファイル"hoge.cpp"として、以下のようにコンパイル

 g++ -O3 -c hoge.cpp -o hoge.o -O2 -Wall -mrtd -g -mno-cygwin -I<jni.hのある場所>

あとはリンク、ここがキモ。
以下のような感じでhoge.defを指定してやる。

 dllwrap -s --export-all --target=i386-mingw32 -mno-cygwin --def hoge.def \
             --driver-name g++ -o ./hoge.dll -mno-cygwin  ./hoge.o -O2

とやるとめでたくhoge.dllができて使えるようになる。
ちなみになにやら激しくワーニングが出たりしているが、キニシナイ。




* C++側からJavaメソッドを呼び出す [#u6d6e692]

** 例 [#c4af78de]

 jclass clazz  = env->FindClass("Hoge");
 
 // staticメソッド
 jmethodID mid = env->GetStaticMethodID ( clazz, "methodname", "signiture" );
 jobject ret = env->CallStaticObjectMethod(clazz, mid, ... );

 // 普通のメソッド
 jmethodID mid = env->GetMethodID ( clazz, "methodname", "signiture" );
 jobject ret = env->CallObjectMethod(clazz, mid, ... );


** シグニチャ(引数)の表現法 [#y7ad065f]

GetMethodID, GetStaticMethodIDの時に指定する"signiture"は、メソッドの引数形式。
以下のような感じで指定する。

|型のシグニチャー | Java の型 |
|Z |boolean|
|B |float|
|C |char|
|S |short|
|I |int|
|J |long|
|F |float|
|D |double|
|Lfully-qualified-class ; |完全指定のクラス|
|[type |typeの配列。type[]|
|( arg-types ) ret-type  |メソッドの型|
|V void |(返り値のときのみ指定)|

- 例
-- int fn ( String[], int );
 ([Ljava/lang/String;I)I

--- [Ljava/lang/String; が第1引数が文字列配列であること
--- 直後のIが第2引数がintであること
--- 括弧の右外側の I が返り値がintであること

を示している。


** 呼出し方法 [#c9e2aaa6]

クラス(jclass)とメソッドID(jmethodID)を取得したら、あとは適当に引数付きで呼ぶだけだが、
戻り値によって呼ぶ関数が変わる。

|戻り値  | 呼ぶ関数 |
|void    |void CallVoidMethod (env, obj, methodID, ...) |
|boolean |jboolean CallBooleanMethod (env, obj, methodID, ...) |
|byte    |jbyte CallByteMethod (env, obj, methodID, ...) |
|int     |jint CallIntMethod  (env, obj, methodID, ...) |
|Object  |jobject CallObjectMethod (env, obj, methodID, ...) |
|以下、おなじような感じなので省略 | short, char, long, double |

例えば、 String fn(int, String) という関数なら
 CallObjectMethod ( env, obj, jintななにか, jobjectななにか );
 env->CallObjectMethod ( obj, jintななにか, jobjectななにか );
で行ける。

引数の数とかは可変長関数使ってるので、気にしなくてもよい。~
ここで言うobjは jobjectななにかで、メソッドのクラスのインスタンス。

関数名の最後に"V"を付けると、可変長引数ではなく、va_listを渡せるようだ(多分)
 jchar CallCharMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);

staticメソッドの場合は、 CallStatic〜 のような名前になって、objの部分が、jclassななにかになる。

CallNonvirtual〜 なんてものもあるので、virtualじゃない呼び出しもできるのかもしれない(ためしてないけど)






* 参考文献 [#pbdbde04]

- http://www.ki.rim.or.jp/~kuro/Java/JNI/index.html