【问题标题】:What is the difference between "jobject" & "jclass" in C++ NDKC ++ NDK中的“jobject”和“jclass”有什么区别
【发布时间】:2019-10-07 09:20:04
【问题描述】:

我从我遵循的教程中做了 2 个不同的实现,我注意到每个参数都有一点不同,1 个参数是 jclass,另一个是 jobject 我根本不使用这些参数,但我尝试进行实验并将它们从jclass 切换到jobjectjobjectjclass,我注意到一切仍然按预期工作,所以我不确定jobjectjinstance 到底做了什么,如果我的方法没有使用这些参数中的任何一个,为什么需要它们?有人可以在我的java类中提供这些方法的正确声明吗我不确定我是否做对了

JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_pauseSounds(JNIEnv* env, jclass thiz);

JNIEXPORT jstring JNICALL Java_org_cocos2dx_cpp_AppActivity_score(JNIEnv *env, jobject instance);

【问题讨论】:

    标签: java c++ android-ndk ndk-build


    【解决方案1】:

    一般来说,

    • 如果JNI函数参数有jclass,那么这个JNI函数对应Java端类方法(原生方法声明withstatic”)。 jclass 是对当前类的引用。
    • 如果JNI函数参数有jobject,那么这个JNI函数对应Java端实例方法(原生方法声明withoutstatic”)。 jobject 是对当前实例的引用。

    具体来说,

    JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_pauseSounds(JNIEnv* env, jclass thiz);
    

    对应于你Java端的静态原生方法(类方法),即

    package org.cocos2dx.cpp
    
    class AppActivity{
        public static native void pauseSounds();
    }
    

    在JNI方法下面

    JNIEXPORT jstring JNICALL Java_org_cocos2dx_cpp_AppActivity_score(JNIEnv *env, jobject instance);
    

    对应于您Java端的本机方法(实例方法),即

    package org.cocos2dx.cpp
    
    class AppActivity{
       public native String score();
    }
    

    如果我的方法没有使用这些参数中的任何一个,为什么需要它们?

    这些参数是自动生成的,如果需要,JNI 会使用这些参数,例如,如果您需要回调 Java 端的 class 方法,则需要如下所示(@987654330 @是方法JNI签名):

    jmethodID staticMethod = env->GetStaticMethodID(clazz, "pauseSounds", "()V");
    

    如果您需要回调 Java 端的 instance 方法,则需要如下所示(()Ljava/lang/String;" 是方法 JNI 签名):

    env->CallObjectMethod(instance, "score", "()Ljava/lang/String;");
    

    【讨论】:

    • 非常感谢您的详细解释!,如果在java代码中将方法声明为静态,为什么我不必在JNIEXPORT旁边声明静态?
    • 你不需要在JNI部分declare static,可以通过jclass参数告诉静态特性,JNI会识别这个方法是一个类方法。另请注意,static 一词在 Java 和 C/C++ 语义上是不同的。
    • 写“extern "C" { };" 时是否需要分号或者我们应该把它写成 "extern "C" { }" ???
    • 不需要分号
    • 您能帮忙解答这个问题吗? stackoverflow.com/questions/56266237/…
    【解决方案2】:

    在 C 中,所有其他 JNI 引用类型都被定义为与 jobject 相同。例如:

    typedef jobject jclass;
    

    在 C++ 中,JNI 引入了一组虚拟类来强制执行子类型关系。例如:

    class _jobject {};
    class _jclass : public _jobject {};
    

    使用示例:

    JNIEnv* env = ...;
    // substitute your desired class's specifier for "java/lang/Class"...
    jclass cls = env->FindClass("java/lang/Class"); 
    jmethodID mid_getName = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
    jstring name = env->CallObjectMethod(cls, mid_getName);
    

    this link goes to oracle documentation of jni for java 6this link goes to documentation of jni in java 8 almost the same.

    【讨论】:

    • 你能展示一下 java 声明如何查找每个方法吗?我不确定他们的假设是否对每个人都不同
    • 令我困惑的是 jstring 方法在 java 中被声明为静态,但我是否还必须在 JNIEXPORT 或 JNICALL 旁边将其声明为静态?
    • 不,你不必声明为静态,JNIEXPORT 和 JNICALL 只是带有一些信息的装饰器 JNIEXPORT 被定义为` 属性 ((visibility ("default") ))` 在我的安装和JNICALL __stdcall 中,_attribute_ 是为某些编译器定义的属性,__stdcall 是用于功能。这告诉编译器适用于设置堆栈、推送参数和获取返回值的规则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2014-03-01
    • 2011-04-05
    • 2011-10-18
    • 1970-01-01
    • 2010-09-09
    相关资源
    最近更新 更多