Search code examples
androidandroid-ndkjava-native-interfacenan

Android: Passing float values from Java to JNI is always NaN


Short version: I can pass double values from Java to C++ using a JNI jdouble. However, when I use floats, the C++ jfloat parameter is always NaN.

Longer version: I'm modifying the hello-gl2 Android sample for VS 2015 which draws a triangle (https://code.msdn.microsoft.com/hello-gl2-android-3b61896c), adding a simple function to rotate the triangle.

In gl_code.cpp:

extern "C" {
    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_updateAngle(JNIEnv * env, jfloat dAngle);
};
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_updateAngle(JNIEnv * env, jfloat dAngle)
{
    __android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "updateAngle: %f", dAngle);
    rotationAngle += dAngle;
}

And in GL2JNILib.java:

public class GL2JNILib {
    public static native void updateAngle(float dAngle);
}

And this is all called from the GL2JNIView.java:

GL2JNILib.updateAngle(0.5f);

The VS debugger shows the value of jfloat dAngle to be nan(3b52bc) no matter what value I pass from Java, logcat shows "nan" and OpenGL confirms this by drawing nothing.

I'm running on a Nexus 9 hardware device. When using the Nexus_5_API_22_x86 emulator, I seem to get many different values, sometimes NaN, even though I'm always passing in 0.5f. If I replace "jfloat" with "jdouble" and "float" with "double" in all the code above, everything works fine on the device and emulator.

What am I doing wrong? Thanks!!


Solution

  • You are missing the 2nd parameter in the native method: jclass. Your method signature in C should be:

    JNIEXPORT void JNICALL
        Java_com_android_gl2jni_GL2JNILib_updateAngle(JNIEnv *env,
                                                      jclass classz,
                                                      jfloat dAngle);
    

    The 2nd parameter is a jclass because your method is static. If it were an instance method for the class then the 2nd parameter would be a jobject (the this for the object.) You might consider using the "javah" tool to help you generate method signatures.