0

I want to call a java method from C that takes an argument T extends Number. I know java by default does the autoboxing for these types for you, but when I try to pass a float or jfloat in the JNI call, I get the following error:

FATAL ERROR in native method: Bad JNI oop argument

Is there an easy way to generate a Number java class or pass it to a Java method argument from C using JNI without caring about the actual primitive type?

Nicholas
  • 7,403
  • 10
  • 48
  • 76

1 Answers1

0

Given Java class

class CC {
    static void callbackMethod(Number number) {
        Log.i("callbackMethod", "arg = " + number);
    }
}

you can use native.c:

#include <jni.h>

jclass floatClass = (*env)->FindClass(env, "java/lang/Float");
jmethodID floatConstructor = (*env)->GetMethodID(env, floatClass, "<init>", "(F)V");
jobject floatObj = (*env)->NewObject(env, floatClass, floatConstructor, (jfloat)1.23);

jclass callbackClass = (*env)->FindClass(env, "CC");
jmethodID callback = (*env)->GetMethodID(env, callbackClass, "callbackMethod", "(java/lang/Object)V");
(*env)->CallVoidMethod(env, callbackClass, callback, floatObj);
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I have improved my question, but I was really hoping there was a way of doing it without having to call the particular classes, like `Float`. – Nicholas Feb 24 '14 at 20:22
  • alas, the answer is negative. – Alex Cohn Feb 24 '14 at 20:43
  • You could not have read my mind :( I'm doing what you have suggested so far, but I was hoping for a more Number neutral implementation. – Nicholas Feb 24 '14 at 20:44
  • What you can do - is to pass a primitive type to Java, e.g. via a ByteBuffer, or formatted String. This way the burden of conversion will be offloaded to Java. But, it's not through Number class, and requires change of the callback function signature, to begin with. `Number` being an **abstract** class, it is impossible to create objects of this class - whether in Java, or through JNI. – Alex Cohn Feb 24 '14 at 20:52
  • 1
    Correct, but java does autoboxing for you. If I pass a number into a member that takes a `Number` argument, java does the conversion for me, I was hoping if I called that through JNI it would do the conversion as well, but it does not. – Nicholas Feb 24 '14 at 20:54
  • 1
    Boxing is done by compiler. That's why `List` is [not the same](http://stackoverflow.com/questions/12216326/what-is-the-difference-between-listnumber-and-list-extends-number) as `List`. JNI is done with no help from Java compiler. You can build your own set of C++ templates that will hide the "boxing" part, but this is seldom worth the hassle. – Alex Cohn Feb 24 '14 at 21:09
  • That's great information. I should do `` instead of ``, I will look into just converting the C++ templates I have into the native form based on class type. – Nicholas Feb 24 '14 at 21:16