0
votes

i want to reference a parameter, Byte[], in a JNI function and replace values of them.
The declaration of JNI is below.

public native void imageprocessing(long inputImage, long inputImage2, long outputImage, long outputImage2, Byte[] sim);

The sim is the target what i want to change.
The interface of it is below.

Java_com_example_duru_opencvtest_MainActivity_imageprocessing(JNIEnv *env, jobject instance, jlong inputImage, jlong inputImage2, jlong outputImage, jlong outputImage2, jobjectArray sim)

it uses jobjectArray type and i want to put int type values of native language into sim object.

so i my method is

        jbyteArray byte_array = env->NewByteArray(4);
        env->SetByteArrayRegion(byte_array, 0, 4, (jbyte*)tempSim);
        jobjectArray object_array = env->NewObjectArray(4, env->FindClass("java/lang/Byte"), byte_array);

        /* ERROR
        (*env).SetObjectArrayElement(sim, 0, (jobject)object_array[0]);
        (*env).SetObjectArrayElement(sim, 1, (jobject)object_array[1]);
        (*env).SetObjectArrayElement(sim, 2, (jobject)object_array[2]);
        (*env).SetObjectArrayElement(sim, 3, (jobject)object_array[3]);
        */     

tempSim is 'int tempSim[4]' and Sim also has 4 length.

(*env).SetObjectArrayElement(sim, 0, (jobject)object_array[0]);

The bold part occur syntax error than the other part have no problem?

1
You can't access Java arrays like that from native code. In this case you need to use the GetObjectArrayElement function. Although I don't really see what the purpose of byte_array and object_array is. Why don't you just pass each of tempSim's values to Byte.valueOf instead? - Michael
Note: NewByteArray is for a primative array (Java: byte[]; JNI: jbytearray), not an object array (Java: Byte[]). - Tom Blodget

1 Answers

2
votes
jclass javaLangByteClass = env->FindClass("java/lang/Byte");
jmethodID javaLangByteConstructor = env->GetMethodID(javaLangByteClass , "<init>", "(B)Ljava/lang/Byte;")
for (int i=0; i<3; i++) {
   jobject nextElement = env->NewObject(javaLangByteClass, javaLangByteConstructor, (jbyte)tempSim[i]);
   env->SetObjectArrayElement(sim, i, nextElement);
   env->DeleteLocalRef(nextElement);
}

See the comment below: Byte.valueOf() may be more efficient than the constructor:

jclass javaLangByteClass = env->FindClass("java/lang/Byte");
jmethodID javaLangByteStaticValueOf = env->GetStaticMethodID(javaLangByteClass , "valueOf", "(B)Ljava/lang/Byte;")
for (int i=0; i<3; i++) {
   jobject nextElement = env->CallStaticObjectMethod(javaLangByteClass, javaLangByteStaticValueOf, (jbyte)tempSim[i]);
   env->SetObjectArrayElement(sim, i, nextElement);
   env->DeleteLocalRef(nextElement);
}