JNI

JNI用のjavaプログラム Hoge.java が jni/mathの下にあるとする.


$ javac jni/math/Hoge.java
$ javah -jni jni.math.Hoge

javah は /usr/bin にパスが通ってない場合あり


# ln -s /usr/java/jdk1.5.0/bin/javah /usr/bin/javah

できた Hoge.h と対応した Hoge.cppを作製.


$ export LD_LIBRARY_PATH=jni/math
$ g++ -IJAVA_HOME/include -IJAVA_HOME/include/linux -l stdc++
jni/math/Hoge.cpp -shared -o jni/math/libHoge.so


頭に"lib"を付けてlibHoge.so としてないと java.lang.UnsatisfiedLinkError

『package にすると java.lang.UnsatisfiedLinkError:』
の場合は下を疑う.(どっかのメーリングリストから)

一般的に,


package pkg;

public class SomeClazz {
public native hello();
}

の場合,ネーティブ・コード側では以下のような関数名を付けなければなりません.

Java_(パッケージ名)_(クラス名)_(メソッド名)
(この場合,Java_pkg_SomeClazz_hello())

下はJNIの呼出しコードの例(これも引用)


include "Fields.h"

/* 以下6つはインスタンスメソッド */
/* インスタンスメソッドの引数はJNIEnv *とjobject */
JNIEXPORT jshort JNICALL Java_Fields_getPublicFieldShort
(JNIEnv *env, jobject this){
/* オブジェクトのクラスを取得 */
jclass clazz = (*env)->GetObjectClass(env, this);
/* 取得したクラスからフィールドIDを取得 */
jfieldID fid = (*env)->GetFieldID(env, clazz,
"publicFieldShort", "S");
/* フィールドIDを使用してオブジェクトからフィールドの値を取得 */
jshort val = (*env)->GetShortField(env, this, fid);
return val;
}

JNIEXPORT jint JNICALL Java_Fields_getPkgPrivateFieldInt
(JNIEnv *env, jobject this){
jclass clazz = (*env)->GetObjectClass(env, this);
jfieldID fid = (*env)->GetFieldID(env, clazz,
"pkgPrivateFieldInt", "I");
jint val = (*env)->GetIntField(env, this, fid);
return val;
}

JNIEXPORT jlong JNICALL Java_Fields_getProtectedFieldLong
(JNIEnv *env, jobject this){
jclass clazz = (*env)->GetObjectClass(env, this);
jfieldID fid = (*env)->GetFieldID(env, clazz,
"protectedFieldLong", "J");
jlong val = (*env)->GetLongField(env, this, fid);
return val;
}

JNIEXPORT jdouble JNICALL Java_Fields_getPrivateFieldDouble
(JNIEnv *env, jobject this){
jclass clazz = (*env)->GetObjectClass(env, this);
jfieldID fid = (*env)->GetFieldID(env, clazz,
"privateFieldDouble", "D");
jdouble val = (*env)->GetDoubleField(env, this, fid);
return val;
}

JNIEXPORT jboolean JNICALL Java_Fields_getPublicStaticFieldBoolean
(JNIEnv *env, jobject this){
jclass clazz = (*env)->GetObjectClass(env, this);
jfieldID fid = (*env)->GetStaticFieldID(env, clazz,
"publicStaticFieldBoolean", "Z");
jboolean val = (*env)->GetStaticBooleanField(env, clazz, fid);
return val;
}

JNIEXPORT jbyte JNICALL Java_Fields_getPkgPrivateStaticFieldByte
(JNIEnv *env, jobject this){
/* オブジェクトのクラスを取得 */
jclass clazz = (*env)->GetObjectClass(env, this);
/* 取得したクラスからフィールドIDを取得 */
jfieldID fid = (*env)->GetStaticFieldID(env, clazz,
"pkgPrivateStaticFieldByte", "B");
/* フィールドIDを使用してクラスからフィールドの値を取得 */
jbyte val = (*env)->GetStaticByteField(env, clazz, fid);
return val;
}

/* 以下二つはスタティックメソッド */
/* スタティックメソッドの引数はJNIEnv *とjclass */
JNIEXPORT jchar JNICALL Java_Fields_getProtectedStaticFieldChar
(JNIEnv *env, jclass clazz){
/* クラスからフィールドIDを取得 */
jfieldID fid = (*env)->GetStaticFieldID(env, clazz,
"protectedStaticFieldChar", "C");
/* フィールドIDを使用してクラスからフィールドの値を取得 */
jchar val = (*env)->GetStaticCharField(env, clazz, fid);
return val;
}

JNIEXPORT jfloat JNICALL Java_Fields_getPrivateStaticFieldFloat
(JNIEnv *env, jclass clazz){
jfieldID fid = (*env)->GetStaticFieldID(env, clazz,
"privateStaticFieldFloat", "F");
jfloat val = (*env)->GetStaticFloatField(env, clazz, fid);
return val;
}