美文网首页
3-ndk学习之jni基础篇(2)

3-ndk学习之jni基础篇(2)

作者: ftd黑马 | 来源:发表于2020-03-18 17:14 被阅读0次

    对象深入学习,参数中有对象

    直接撸代码:首先有两个实体类Person和Student

    package com.example.myapplication;
    
    import android.util.Log;
    
    public class Student {
    
        private static final String TAG = Student.class.getSimpleName();
    
        public String name;
        public int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
            Log.d(TAG, "setName: " + name);
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
            Log.d(TAG, "setAge: " + age);
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    package com.example.myapplication;
    
    import android.util.Log;
    
    public class Person {
    
        private static final String TAG = Person.class.getSimpleName();
    
        public void setStudent(Student student) {
            Log.d(TAG, "setStudent: " + student.toString());
        }
    
    }
    

    然后MainActivity中调用jni方法,没有任何参数的
    jni中代码如下:

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_myapplication_MainActivity_test01(JNIEnv *env, jobject instance) {
        //我想在这个函数中,直接调用Person的setStudent方法
    
        //1,获取到全包名
        const char * person_class_str = "com/example/myapplication/Person";
        //2,获取到字节码对象
        jclass person_class = env->FindClass(person_class_str);
        //3,需要获取到jobject的对象
        jobject person = env->AllocObject(person_class);
        //4,调用person的setStudent方法,需要先获取methodId和签名
    
        const char * sig = "(Lcom/example/myapplication/Student;)V";
        jmethodID setStudent = env->GetMethodID(person_class,"setStudent",sig);
    
        //5,因为setStudent的参数是Student,所以还需要创建Student的对象
        const char *student_class_str = "com/example/myapplication/Student";
        jclass student_class = env->FindClass(student_class_str);
        jobject student = env->AllocObject(student_class);
    
        //6,给我们创建出来的student对象赋值
        sig = "(Ljava/lang/String;)V";
        jmethodID setName = env->GetMethodID(student_class,"setName",sig);
        jstring value = env->NewStringUTF("piter");
        env->CallVoidMethod(student,setName,value);
    
        sig = "(I)V";
        jmethodID setAge = env->GetMethodID(student_class, "setAge", sig);
        env->CallVoidMethod(student, setAge, 23);
    
        //7,调用Person的setStudent方法
        env->CallVoidMethod(person,setStudent,student);
    
        //8,回收
        env->DeleteLocalRef(student_class); // 遇到jclass  jobject,都要记得回收
        env->DeleteLocalRef(student);
        env->DeleteLocalRef(person);
        env->DeleteLocalRef(person_class);
    }
    

    运行结果为


    image.png

    全局引用和局部引用

    随意来一个实体对象Dog

    public class Dog {
        public Dog() {
            Log.d("Dog", "Dog: 构造方法被C++中直接实例化了....");
        }
    }
    

    jni中代码如下:

    jclass dogClass;
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_myapplication_MainActivity_testDog(JNIEnv *env, jobject instance) {
        // 局部引用:如果在函数里面,是在栈区,不用回收,函数结束,会自动回收
        if (dogClass == NULL) { // 方法刚进来满足,执行完后虽然被释放,但是还是不等于Null
            // 全局引用
            const char * dog_class_str = "com/example/myapplication/Dog";
            jclass temp = env->FindClass(dog_class_str);
            dogClass = static_cast<jclass>(env->NewGlobalRef(temp));
        }
    
        // Java构造方法的实例化
        const char * sig = "()V";
        const char * method = "<init>"; // Java构造方法的标识
        jmethodID init = env->GetMethodID(dogClass, method, sig);
        env->NewObject(dogClass, init); // 方法执行完毕,dogClass自动释放,但是不等于null,由于dogClass 是悬空的,直接报错
        //所以需要手动释放,但是手动释放完毕以后,dogClass还是不等于NULL,还需要手动改为Null
    }
    
    // 此函数就是为了 手动释放全局并且置为NULL
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_kevin_ndk09_1code_MainActivity_testUnDog(JNIEnv *env, jobject thiz) {
        // TODO: implement testUnDog()
        if(dogClass != NULL) {
            env->DeleteGlobalRef(dogClass);
            dogClass = NULL;
        }
    }
    

    相关文章

      网友评论

          本文标题:3-ndk学习之jni基础篇(2)

          本文链接:https://www.haomeiwen.com/subject/qroqyhtx.html