在JNI中不能使用GetIntField在java类Android中获取值

In JNI Cannot using GetIntField get the value in the java class Android

本文关键字:Android 获取 java JNI 不能 GetIntField      更新时间:2023-10-16

我尝试在本机类字段mInt中获得值。该类是由SimpleJNI创建的。在这个示例中,我将mInt值设置为9。JNI函数添加尝试通过使用GetIntField来获取mInt值。在add函数中应该返回9。但是似乎GetIntfield无法在这个任务中找到字段。我如何从JNI获得mInt ?谢谢你的评论。

这是JNI源代码。

static jfieldID gNative;
static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
    int result = a + b;
    LOGI("%d + %d = %d", a, b, result);
    int value = env->GetIntField(thiz , gNative);
    result = value;
    return result;
}
static const char *classPathName = "com/example/android/simplejni/Native";
static JNINativeMethod methods[] = {
    {"add", "(II)I", (void*)add },
};
static int registerNativeMethods(JNIEnv* env, const char* className,
    JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        LOGE("Native registration unable to find class '%s'", className);
        return JNI_FALSE;
    }
    gNative = env->GetFieldID(clazz, "mInt" , "I");
    if(gNative == NULL) {
        LOGE("Get mInt field id fail");
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        LOGE("RegisterNatives failed for '%s'", className);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
static int registerNatives(JNIEnv* env)
{
    if (!registerNativeMethods(env, classPathName,
            methods, sizeof(methods) / sizeof(methods[0]))) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}
typedef union {
    JNIEnv* env;
    void* venv;
} UnionJNIEnvToVoid;
jint JNI_OnLoad(JavaVM* vm, void* reserved) 
{
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv* env = NULL;
    LOGI("JNI_OnLoad");
    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("ERROR: GetEnv failed");
        goto bail;
    }
    env = uenv.env;
    if (registerNatives(env) != JNI_TRUE) {
        LOGE("ERROR: registerNatives failed");
        goto bail;
    }
    result = JNI_VERSION_1_4;
    bail:
    return result;
}

Native类在这里。公共函数setval用于设置该类的mInt值。

public class Native {
    private int mInt;
    static {
        System.loadLibrary("simplejni");
    }
    public void setval(int k){
        mInt = k;
    }
    static native int add(int a, int b);
}

SimpleJNI的代码列表如下。

public class SimpleJNI extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        Native nv = new Native();
        nv.setval(9);
        int sum = nv.add(2, 3);
        tv.setText("2 + 3 = " + Integer.toString(sum));
        setContentView(tv);
    }
}

你的JNI中的add函数是错误的/不是原始代码

static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
int result = a + b;
LOGI("%d + %d = %d", a, b, result);
int value = env->GetIntField(thiz , gNative);
result = value;
return result;  

}

首先,JNI函数签名类似于

Java_native_add(JNIEnv *env, jobject this, jint a, jint b)

尝试使用javah

生成函数签名

不确定add函数的意义是什么,除非您只是为了测试JNI代码而编写它。如果是这样的话,一个较小的例子会更容易理解。无论如何,希望这对你有所帮助

我已经找到了JNI add函数无法从GetIntField获取值的根本原因。因为本机函数声明不能是静态的。应该是

public native int add(int a, int b);