从本机C / C ++ code调用JAVA类成员 [英] Calling JAVA class member from Native C/C++ code

查看:134
本文介绍了从本机C / C ++ code调用JAVA类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个OpenGL C / C ++应用程序,我移植到Android通过的Andr​​oid NDK,JNI支持。我在从Java回调执行code困难来自本机发出信号。

I'm writing an OpenGL C/C++ application which i'm porting to Android through Android NDK, JNI support. I'm having difficulties executing code from JAVA callback signaled from native.

下面是code:

class OpenGLSurfaceView extends GLSurfaceView 
{
…
     public OpenGLSurfaceView(Context context, int deviceWidth, int deviceHeight) 
    {
        super(context);
        nativeObj = new NativeLib();
        mRenderer = new OpenGLRenderer(context, nativeObj, deviceWidth, deviceHeight);
        setRenderer(mRenderer);
        setRenderMode(RENDERMODE_WHEN_DIRTY);
    }
…
    private void CallBack()
    {
        // force redraw
        requestRender();
    }
}


class OpenGLRenderer implements GLSurfaceView.Renderer 
{
    …
public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    {
        nativeObj.init(…);
        nativeObj.cachejavaobject(JNIEnv *env, jobject obj); // for caching obj on native side
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) 
    {
    }

    public void onDrawFrame(GL10 gl) 
    {
        nativeObj.draw(…);
    }
}

而在本土codeI有一个功能texturesLoaded(),该信号时完全加载在另一个线程一些纹理和我需要强制从nativeLib.draw在Java端刷新(...)。下面是我如何做到这一点:

And in native code i have a function texturesLoaded() that is signaled when some textures are loaded completely on another thread and i need to force a refresh from nativeLib.draw(…) on the JAVA side. Here is how i do it :

我缓存JavaVM的,JCLASS,jMethodID上JNI_OnLoad和gJObjectCached

I cache the JavaVM, jClass, jMethodID on JNI_OnLoad, and gJObjectCached

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
gJVM = jvm;  // cache the JavaVM pointer

LogNativeToAndroidExt("JNILOAD!!!!!!!!!!");
JNIEnv *env;
int status = gJVM->GetEnv((void **)&env, JNI_VERSION_1_6);
if(status < 0)
{
    LogNativeToAndroidExt("Failed to get JNI environment, assuming native thread");
    status = gJVM->AttachCurrentThread(&env, NULL);
    if(status < 0)
    {
        LogNativeToAndroidExt("callback_handler: failed to attach current thread");
        return JNI_ERR;
    }
}

gJClass = env->FindClass("com/android/newlineactivity/NewLineGLSurfaceView");
if(gJClass == NULL)
{
    LogNativeToAndroidExt("Can't find Java class.");
    return JNI_ERR;
}

gJMethodID = env->GetMethodID(gJClass, "callback", "()V");
if(gJMethodID == NULL)
{
    LogNativeToAndroidExt("Can't find Java method void callback()");
    return JNI_ERR;
}

return JNI_VERSION_1_6;

}

JNIEXPORT void Java_com_android_OpenGL_NativeLib_cachejavaobject(JNIEnv* env, jobject obj)
{
    // cache the java object
    gJObjectCached = obj;
...
}

,然后texturesLoaded()我做的:

and then on texturesLoaded() i do :

void texturesLoaded()
{
    // Cannot share a JNIEnv between threads. You should share the JavaVM, and use JavaVM->GetEnv to discover the thread's JNIEnv
    JNIEnv *env = NULL;
    int status = gJVM->GetEnv((void **)&env, JNI_VERSION_1_6);
    if(status < 0)
    {
        LogNativeToAndroidExt("callback_handler: failed to get JNI environment, assuming native thread");
        status = gJVM->AttachCurrentThread(&env, NULL);
        if(status < 0)
        {
            LogNativeToAndroidExt("callback_handler: failed to attach current thread");
            return;
        }
    }

    LogNativeToAndroidExt("Calling JAVA method from NATIVE C/C++");
    env->CallVoidMethod(gJObjectCached, gJMethodID);
    LogNativeToAndroidExt("DONE!!!");
}

结果......从本机端我得到的类,我得到的方法,方法被调用,但是当它到达/调用requestRender()内(或试图访问GLSurfaceView任何其他成员方法崩溃!)

Result… from native side i get the class, i get the method, method gets called, but when it reaches/calls requestRender() inside(or trying to access any other member method of GLSurfaceView it crashes!)

我不能尝试与CallStaticVoidMethod(gJClass,gjMethodID);因为当时我没有获得requestRender();

I cannot try with CallStaticVoidMethod(gJClass, gjMethodID); because then i don't have access to requestRender();

任何想法或意见,也许我在这里做得不对。

Any ideas or opinions, maybe i'm doing something wrong here.

感谢

推荐答案

您需要创建的全局引用的给你走藏匿的类/对象。要保存的引用的本地引用的,不能跨线程共享,并在运行时清理JNI本地参考堆栈消失。

You need to create global references to the class/object that you stash away. The references you're saving are local references, which can't be shared across threads and disappear when the runtime cleans up the JNI local reference stack.

查看的Sun /甲骨文全球和本地引用文档,并检查了JNI方法的 的JNIEnv :: NewGlobalRef 和的 的JNIEnv :: DeleteGlobalRef

Check out the Sun/Oracle documentation for global and local references, and check out JNI methods JNIEnv::NewGlobalRef and JNIEnv::DeleteGlobalRef.

gJClass = env->NewGlobalRef(env->FindClass( ... ));

gJObjectCached = env->NewGlobalRef(obj);

(编辑:原来你不需要的方法ID全局引用)

这篇关于从本机C / C ++ code调用JAVA类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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