I have a JNI-Interface between C++ and Java. I want to pass a callback function as a parameter in a function on java side. This will be called later in C ++ via JNI and should return me a string.
This is what I have:
Java:
instance.LoadFileFromPath(Object callbackObject);
The function for callbackObject is this:
public String CallbackTest (String str)
{
//Log-Ausgabe
System.out.println("CallbackString: " + str);
return str;
}
This object is saved into a global variable in JNI:
jobject g_callbackObject;
jmethodID g_callbackMethod;
JNIEnv* g_env;
JNIEXPORT jboolean JNICALL xx_LoadFileFromPath (JNIEnv* env, jobject o, jobject callbackObject)
{
jclass callBackClass = env->GetObjectClass(callbackObject);
jmethodID callBackMethode = env->GetMethodID(callBackClass, "CallbackTest ", "(Ljava/lang/String;)Ljava/lang/String;");
g_env = env;
g_callbackObject = callbackObject;
g_callbackMethod = callBackMethode;
bool res = LoadFileFromPath(LoadFileFromPathCallbackWrapper);
return res;
}
Later in C++ I want to call the Java-Function "CallbackTest":
char* LoadFileFromPathCallbackWrapper(char* fileName)
{
jstring res = (jstring)g_env->CallObjectMethod(g_callbackObject, g_callbackMethod, g_env->NewStringUTF(fileName));
const char* nativeStr = g_env->GetStringUTFChars(res, NULL);
#ifdef OS_LINUX
char* result = strdup(nativeStr);
#else
char* result = _strdup(nativeStr);
#endif
g_env->ReleaseStringUTFChars(res, nativeStr);
return result;
}
Everything looks okay, but g_env->CallObjectMethod
returns NULL. The Log from CallbackTest
in java is never printed.
I am not allowed to change the interface.
Does anyone have an idea, what could be the problem?
Thanks!
_____ Edit:
Thanks, the method name in jmethodID callBackMethode = env->GetMethodID()
was wrong, because I had to change the names for privacy reasons. I edited the question. ExceptionCheck returns 0.
I tried the following now:
JavaVM* g_vm;
jobject g_callbackObject;
jmethodID g_callbackMethod;
//JNIEnv* g_env;
JNIEXPORT jboolean JNICALL xx_LoadFileFromPath (JNIEnv* env, jobject o, jobject callbackObject)
{
env->GetJavaVM(&g_vm);
jint version = env->GetVersion();
jclass callBackClass = env->GetObjectClass(callbackObject);
jboolean check = env->ExceptionCheck(); //returns 0
jmethodID callBackMethode = env->GetMethodID(callBackClass, "CallbackTest", "(Ljava/lang/String;)Ljava/lang/String;");
check = env->ExceptionCheck(); //returns 0;
//g_env = env;
g_callbackObject = callbackObject;
g_callbackMethod = callBackMethode;
bool res = LoadFileFromPath(LoadFileFromPathCallbackWrapper);
return res;
}
bool GetJniEnv(JavaVM* vm, JNIEnv **env) {
bool did_attach_thread = false;
*env = nullptr;
int getEnvStat = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
if (vm->AttachCurrentThread((void**)env, NULL) == JNI_OK) {
did_attach_thread = true;
}
else {}
}
return did_attach_thread;
}
char* LoadFileFromPathCallbackWrapper(char* fileName)
{
JNIEnv* g_env;
GetJniEnv(g_vm, &g_env);
jstring res = (jstring)g_env->CallObjectMethod(g_callbackObject, g_callbackMethod, g_env->NewStringUTF(fileName));
jboolean check = g_env->ExceptionCheck(); **//returns 1**
const char* nativeStr = g_env->GetStringUTFChars(res, NULL);
#ifdef OS_LINUX
char* result = strdup(nativeStr);
#else
char* result = _strdup(nativeStr);
#endif
g_env->ReleaseStringUTFChars(res, nativeStr);
return result;
}
It's still the same error... :(