如何调用从C Java函数 [英] How to call Java function from c

查看:234
本文介绍了如何调用从C Java函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚持这一点,我需要从C调用Java函数/ C ++。

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

在示例和教程我只看到一个Java应用程序调用的交流方法,并在相同的方法调用另一个Java方法,但我想要做的是从任何部分code调用Java方法。这是我有:

In the examples and tutorials i only see a java app calling a c method, and in this same method calling another java method, but what I want to do is to call a 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);
}

但总是崩溃,我试过没有NewGlobalRef,使用替代ENV在JNI_Function MENV,我试图让从JNI_OnLoad方法ID,但总是死机。

but is always crashing, I've tried without the NewGlobalRef, using mEnv instead of env in the JNI_Function, I've tried getting the method id from the JNI_OnLoad, but always crashes.

这是日志我得到:

02-15 18:09:48.520:W / dalvikvm(27904):JNI警告:主题ID = 1使用ENV从主题ID = 0

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

推荐答案

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

You can't reuse JNIEnv because it is specific to the calling thread. To call (non-static) Java method from the 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);
}

这code段没有进行测试。为prevent内存泄漏,不要忘了当参考对象不会需要更多的在你的Java code调用 nativeRelease()方法。

This code snippet is not tested. To prevent memory leak, don't forget to call nativeRelease() method in your Java code when the reference to the object will not needed any more.

有关详细信息,请参见 Java本机接口的文档。

See The Java Native Interface documentation for more details.

这篇关于如何调用从C Java函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆