Javaのnativeメソッド
なにはともれ、共有ライブラリを作成せなあかん
いろいろ方法はあるんだろうけど、一番簡単そうな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ができて使えるようになる。 ちなみになにやら激しくワーニングが出たりしているが、キニシナイ。
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, ... );
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 | (返り値のときのみ指定) |
([Ljava/lang/String;I)I
を示している。
クラス(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じゃない呼び出しもできるのかもしれない(ためしてないけど)