I\'m trying to use a JNI function to create a Java class and set some properties of that class using the DeviceId.java constructor method. I\'m able to get the constructor
When you called GetMethodID
, you provided the signature for the two-arg constructor. Thus, you just need to pass your jstring
and a jbytearray
when you call NewObject
- for example:
return (*env)->NewObject(env, c, cnstrctr, id, cache);
You don't need to call the setId
and setCache
methods unless you decide to call the 0-arg constructor - and that just complicates your code since you'll have to call GetMethodID
for those and call them. Simpler to continue down the route you're on.
I wanted to return a custom Java object from JNI's cpp code back to Java. The solution is to return a jobject
from cpp function and use our custom Java object in native method declaration.
public class PyError {
public String message;
public boolean occurred;
public PyError(boolean occurred, String message){
this.message = message;
this.occurred = occurred;
}
}
and method declaration in Java:
native PyError nativePythonErrorOccurred();
on the cpp side:
extern "C" JNIEXPORT jobject JNICALL
Java_com_your_package_nativePythonErrorOccurred(JNIEnv *env, jobject obj) {
jclass javaLocalClass = env->FindClass("com/your/package/PyError");
if (javaLocalClass == NULL) {
LOGP("Find Class Failed.\n");
} else {
LOGP("Found class.\n");
}
jclass javaGlobalClass = reinterpret_cast<jclass>(env->NewGlobalRef(javaLocalClass));
// info: last argument is Java method signature
jmethodID javaConstructor = env->GetMethodID(javaGlobalClass, "<init>", "(ZLjava/lang/String;)V");
if (javaConstructor == NULL) {
LOGP("Find method Failed.\n");
} else {
LOGP("Found method.\n");
}
jobject pyErrorObject = env->NewObject(javaGlobalClass, javaConstructor, true, env->NewStringUTF("Sample error body"));
return pyErrorObject;
}
Determine the signature of the method using
javap -s java.your.package.YourClass
.
Also, have a look here.
If you encounter error similar to: JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba
your method signature is wrong, you're passing wrong arguments to env->NewObject()
or you're not using global state of jni objects - more here.