How to call Java function from c

I'm stuck with this, I need to call a Java function from c / C ++.

In the examples and tutorials, I see only a java application calling the c method, and in the same method calling another java method, but I want to call the java method from any part of the code. This is what I have:

static JNIEnv mEnv; static jclass mClassAndroidActivity; static mMethodSayHello; JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) { mEnv = env; jclass cls = (*env)->GetObjectClass(env, obj); mClassAndroidActivity = (*env)->NewGlobalRef(env, cls); mMethodSayHello = (*env)->GetMethodID (env, mClassAndroidActivity, "SayHello", "(Ljava/lang/String;)V"); } //this method is called from a cpp void nativeSayHello(char* msg) { jstring string = (*mEnv)->NewStringUTF(mEnv, msg); (*mEnv)->CallVoidMethod(mEnv, mClassAndroidActivity, mMethodSayHello, string); } 

but always fail, I tried without NewGlobalRef, using mEnv instead of env in JNI_Function, I tried to get the method identifier from JNI_OnLoad, but always fail.

This is the journal I received:

02-15 18: 09: 48.520: W / dalvikvm (27904): JNI WARNING: threadid = 1, using env from threadid = 0

+4
source share
1 answer

You cannot reuse JNIEnv because it is specific to the calling thread. To call a (non-static) Java method from native code, you need something like this:

 static JavaVM *gJavaVM; static jobject gCallbackObject = NULL; JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { gJavaVM = vm; return JNI_VERSION_1_6; } JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) { // ... gCallbackObject = (*env)->NewGlobalRef(env, obj); } JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeRelease)(JNIEnv* env, jobject obj) { (*env)->DeleteGlobalRef(env, gCallbackObject); gCallbackObject = NULL; } //this method is called from native code void nativeSayHello(char* msg) { int status; JNIEnv *env; int isAttached = 0; if (!gCallbackObject) return; if ((status = (*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { if ((status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { return; } isAttached = 1; } jclass cls = (*env)->GetObjectClass(env, gCallbackObject); if (!cls) { if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); return; } jmethodID method = (*env)->GetMethodID(env, cls, "SayHello", "(Ljava/lang/String;)V"); if (!method) { if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); return; } jstring string = (*mEnv)->NewStringUTF(mEnv, msg); (*env)->CallVoidMethod(env, gCallbackObject, method, string); if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); } 

This piece of code has not been verified. To prevent memory leaks, be sure to call the nativeRelease() method in your Java code if you no longer need a reference to the object.

See the Java Native Interface Documentation for more information.

+9
source

Source: https://habr.com/ru/post/1396752/


All Articles