Search code examples
javac++compiler-errorsjava-native-interfaceinvocation

Error creating args array of jvalues for NewObjectA() function - JNI Invocation API


I'm trying to create a jobject in C++ by calling the NewObjectA() function using the JNI invocation API. However, I am unsure how I should pass arguments into the constructor. The JNI API documentation states:

jobject NewObjectA(JNIEnv *env, jclass clazz,jmethodID methodID, const jvalue *args);

NewObjectA

Programmers place all arguments that are to be passed to the constructor in an args array of jvalues that immediately follows the methodID argument. NewObjectA() accepts the arguments in this array, and, in turn, passes them to the Java method that the programmer wishes to invoke.

In my case the constructor requires two java strings passed to it. I have therefore tried the following:

jclass jcls_File = env->FindClass("java/io/File");
jmethodID  File_constructor = env->GetMethodID(jcls_File, "<init>","(Ljava/lang/String;Ljava/lang/String;)V");
jstring home = ctojstring(env,"/home/workspace");
jstring filename = ctojstring(env,"mydatafile");
jvalue FileLocationParams[] = {home,filename};  // COMPILE ERROR HERE.
jobject MyDataFile = env->NewObjectA(jcls_File, File_constructor,FileLocationParams);

Where ctojstring is just the following function:

jstring ctojstring(JNIEnv *env,std::string mystring){
    return env->NewStringUTF(mystring.c_str());
}

But when I try to compile I get the following error in Eclipse:

error: invalid conversion from ‘jstring {aka _jstring*}’ to ‘jboolean {aka unsigned char}’ [-fpermissive]

Any thoughts on why this is happening?


Solution

  • The jvalue is of type union.

    And it is declared as follows:

    typedef union jvalue { 
        jboolean z; 
        jbyte    b; 
        jchar    c; 
        jshort   s; 
        jint     i; 
        jlong    j; 
        jfloat   f; 
        jdouble  d; 
        jobject  l; 
    } jvalue;
    

    If you want to assign jstring to jvalue you could do as below.

    jvalue FileLocationParams[2];
    FileLocationParams[0].l = home;
    FileLocationParams[1].l = filename;
    

    Instead of

    jvalue FileLocationParams[] = {home,filename};  // COMPILE ERROR HERE.
    

    As it will try to assign home and filename to first member of jvalue which is jboolean z.