简体   繁体   中英

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

I try to get the value in the Native class field mInt. This class is created by SimpleJNI. In this sample I set the mInt value to 9. JNI function add try to get the mInt value by using GetIntField. It should return 9 in add function. But it seems GetIntfield cannot find the field in this jobject. How do I get the mInt from JNI? Thanks for your comment.

Here is the JNI source code.

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;
}

The Native class is here. public function setval is used to set mInt value in this class.

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 is code list as follow.

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);
    }

}

Your add function in JNI is wrong/ not the original code

 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; 

}

Firstly the JNI function signature will be something like

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

Try to generate the function signature using javah

Not sure what the point of the add function is, unless you wrote it just for testing out JNI code. If so, a smaller example would have been easier to understand. Anyway hope this helps

I already found the root cause of why JNI add function cannot get value from GetIntField. Because the native function declare cannot be static. It should be

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM