gpt4 book ai didi

java - 如何从 C 调用 Java 函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:00:16 33 4
gpt4 key购买 nike

我受困于此,我需要从 c/c++ 调用 Java 函数。

在示例和教程中,我只看到一个 java 应用程序调用一个 c 方法,并在同一个方法中调用另一个 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=1 使用来自 threadid=0 的环境

最佳答案

您不能重用 JNIEnv,因为它特定于调用线程。要从 native 代码调用(非静态)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);
}

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

参见 The Java Native Interface文档以获取更多详细信息。

关于java - 如何从 C 调用 Java 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9304185/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com