如何从c调用Java函数

我坚持这个,我需要从c / c ++调用Java函数。

在示例和教程中,我只看到一个java app调用ac方法,并且在同一个方法中调用另一个java方法,但我想要做的是从代码的任何部分调用java方法。 这就是我所拥有的:

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); } 

但是总是崩溃,我试过没有NewGlobalRef,在JNI_Function中使用mEnv代替env,我试过从JNI_OnLoad获取方法id,但总是崩溃。

这是我得到的日志:

02-15 18:09:48.520:W / dalvikvm(27904):JNI警告:使用来自threadid = 0的env的threadid = 1

您不能重用JNIEnv因为它特定于调用线程。 要从本机代码调用(非静态)Java方法,您需要这样的东西:

 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); } 

此代码段未经过测试。 为了防止内存泄漏,当不再需要对象的引用时,不要忘记在Java代码中调用nativeRelease()方法。

有关更多详细信息,请参阅Java Native Interface文档。