上一章写了JAVA通过JNI调用C库的方法,这一章记录下JAVA通过JNI调用JAVA的方法,
先实现两个JAVA类
public class JniFuncMain
{
private static int staticIntField = 300;
static {
System.loadLibrary("jnifunc");
}
public static native JniTest createJniObject();
public static void main(String[] args)
{
System.out.println("[Java] createJniObejct() 调用本地方法");
JniTest jniObj = createJniObject();
jniObj.callTest();
}
}
class JniTest
{
private int intField;
public JniTest(int num)
{
intField = num;
System.out.println("[Java] 调用JniTest 对象的构造方法: intField = " + intField);
}
public int callByNative(int num)
{
System.out.println("[Java] JniTest 对象的callByNative (" + ")调用");
return num;
}
public void callTest()
{
System.out.println("[Java] JniTest 对象的callTest() 方法调用: intField = " + intField);
}
}实现C库
#include "JniFuncMain.h"
#include
JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject(JNIEnv *env, jclass clazz)
{
jclass targetClass;
jmethodID mid;
jobject newObject;
jstring helloStr;
jfieldID fid;
jint staticIntField;
jint result;
// 获得JniFuncMain类的staticIntField变量值
fid = env->GetStaticFieldID(clazz, "staticIntField", "I");
staticIntField = env->GetStaticIntField(clazz, fid);
printf("[cpp]get JniFuncMain private field staticIntField value\n");
printf(" JniFuncMain.staticIntField = %d\n", staticIntField);
// 查找要访问的成员所在的类
targetClass = env->FindClass("JniTest");
// 查找构造方法
mid = env->GetMethodID(targetClass, "", "(I)V");
// 1."(I)V"是用javap反编译工具反编译JniTest的成员
// 获得的签名。GetMethodID方法会根据此签名找到该方法。
// 反编译class文件命令,例子: javap -s -p 类名
// 2. 第一个参数不是JNIEnv*类型是因为此代码是c++代码。原理类似于this指针。
// 3. 只有获得构造方法时第2个参数是,其他的,直接传入方法名称即可。
// 生成JniTest对象
printf("[cpp]JniTest object generate...\n");
newObject = env->NewObject(targetClass, mid, 100);
// 调用jniTest对象的方法返回一个值,本地打印出来
mid = env->GetMethodID(targetClass, "callByNative", "(I)I");
result = env->CallIntMethod(newObject, mid, 200);
// 再调用一下jni设置字段的方法
fid = env->GetFieldID(targetClass, "intField", "I");
printf("[cpp]:set JniTest object field intField = 200\n");
env->SetIntField(newObject, fid, 200);
return newObject;
}