如何调用传递给JNI`jobject`的Java对象的子类/子类的方法

Posted

技术标签:

【中文标题】如何调用传递给JNI`jobject`的Java对象的子类/子类的方法【英文标题】:How to call a method of a subclass / child class of an Java Object passed to JNI `jobject` 【发布时间】:2018-06-24 23:30:07 【问题描述】:

我有:

public class MyEntity 
    private String _myEntityType;

    public String get_myEntityType() 
        return _myEntityType;
    

    public void set_myEntityType(String _myEntityType) 
        this._myEntityType = _myEntityType;
    
  

然后:

public class MyObjectEntity extends MyEntity 
    public MyObjectEntity() 
        super();
    

    private String _myObjectDescription;

    public String get_myObjectDescription() 
        return _myObjectDescription;
    

    public void set_myObjectDescription(String _myObjectDescription) 
        this._myObjectDescription = _myObjectDescription;
    
  

现在我开始接触 JNI。

public class MyPers 

    // Load the 'my-pers-lib' library on application startup.
    static 
        System.loadLibrary("my-pers-lib");
    

    public native Long myPersInit(MyEntity myEntity);
  

然后:

#include <jni.h>

#include <android/log.h>

extern "C"
JNIEXPORT jobject JNICALL
Java_my_ca_my_1gen_1lib_1pers_c_1libs_1core_RevPers_myPersInit(JNIEnv *env, jobject instance,
  jobject myEntity) 

    jclass myEntityClazz = env->GetObjectClass(myEntity);

    /** START GET STRING **/

    const char *myEntityType;

    // and the get_myObjectDescription() method
    jmethodID get_myObjectDescription = env->GetMethodID
    (myEntityClazz, "get_myObjectDescription", "()Ljava/lang/String;");

    // call the get_myObjectDescription() method
    jstring s = (jstring) env->CallObjectMethod
    (myEntity, get_myObjectDescription);

    if (s != NULL) 
        // convert the Java String to use it in C
        myEntityType = env->GetStringUTFChars(s, 0);
        __android_log_print(ANDROID_LOG_INFO, "MyApp", "get_myObjectDescription :  %s\n",
            myEntityType);

        env->ReleaseStringUTFChars(s, myEntityType);
    

    /** END GET STRING **/

    return myEntityGUID;

  

我开始一切:

MyObjectEntity myObjectEntity = new MyObjectEntity();
myObjectEntity.set_myObjectDescription("A Good Day To Find Answers To Life's Important Questions.");

MyPers revPers = new MyPers();

Log.v("MyApp", "GUID : " + myPers.myPersInit(myObjectEntity));  

我得到的错误是:

JNI CallObjectMethodV called with pending exception java.lang.NoSuchMethodError: no non-static method "Lmy_app/MyEntity;.get_myObjectDescription()Ljava/lang/String;"  

问题

在这种情况下,如何调用传递给 JNI jobjectmyEntity 的 Java 对象的子类/子类的方法?

extern "C"
JNIEXPORT jobject JNICALL
Java_myPersInit(JNIEnv *env, jobject instance, jobject myEntity)  

提前谢谢大家。

【问题讨论】:

【参考方案1】:

我怎样才能去调用一个子类/子类的方法 Java 对象传递给 JNI 对象,在这种情况下是 myEntity?

这个问题没有意义。 对象没有子类,有。无论给定对象的类碰巧定义了您可以在该对象上调用的方法。您似乎试图询问如何调用本机方法参数的声明类型的子类型的方法,但这样一个问题的前提与您这样做的实际事实背道而驰,因为您调用任何其他实例的方式完全相同来自 JNI 的方法。

考虑:在 Java 中,您将向下转换为子类型,然后假设转换成功,您将正常调用所需的方法。另一方面,在 JNI 中,对象引用不通过指向的对象类型来区分(它们都是jobjects),因此不涉及强制转换;您只需直接正常调用所需的方法即可。

当然,如果目标对象的类没有提供这样的方法,就会出现JNI错误。做你描述的事情是否是一个好主意是一个完全独立的问题。

【讨论】:

以上是关于如何调用传递给JNI`jobject`的Java对象的子类/子类的方法的主要内容,如果未能解决你的问题,请参考以下文章

android jni介绍

Android在C ++ JNI代码中从另一个活动类调用Java函数

JNI调用坑

java 通过jni 向 c 传递一个 java 对象, c 如何取得这个对象的属性值?

如何修改从java传递给jni的int参数

将 JNI -> jobject(基本上是映射和/或 java 文件中的映射)转换为 std::map(c++)