JNI中java和jni的基本交互

基本数据类型的使用

MainActivity中修改 name 的值,将值Lsm修改为TimmyDuncan
MainActivity 代码:

class MainActivity : AppCompatActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
  
        // Example of a call to a native method  
        findViewById<TextView>(R.id.sample_text).text = stringFromJNI()  
        println("name修改前是:$name")  
        changeName()  
        println("name修改后是:$name")  
        println("age修改前是:$age")  
        changeAge()  
        println("age修改后是:$age")  
    }  
    val name:String = "Lsm"  
    private val age:Int = 18;//用native修改为 29  
  
    /**  
     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    external fun stringFromJNI(): String  
    external fun changeName()  
    external fun changeAge()  
    companion object {  
        // Used to load the 'native-lib' library on application startup.  
        init {  
            System.loadLibrary("native-lib")  
        }  
    }  
}

想要修改Lsm的值 先创建external fun changeName() 通过changName,修改Lsm
native-lib.cpp 相关代码:

#include <jni.h>  
#include <string>  
  
extern "C" JNIEXPORT jstring JNICALL  
Java_com_lsm_sociax_jni_1test_MainActivity_stringFromJNI(  
        JNIEnv* env,  
        jobject /* this */) {  
    std::string hello = "Hello from C++";  
    return env->NewStringUTF(hello.c_str());  
}  
  
extern "C"//下面的代码采用C的编译方式,无论是C还是C++最终都是JNINativeInterface* 结构体  
JNIEXPORT //JNIEXPORT:JNI重要标记关键字,不能少,少了会报错/规则(标记为该方法可以被外部调用),为了统一Window版本,as可以因为android是linux  
void //void 代表java中的void  
JNICALL //也是一个关键字,(可以少的) jni call(约束函数入栈顺序和堆栈内存清理的规则  
//方法名 = 包名 +类名 + 方法  
// jobject 谁调用 谁的对象this 静态的话是jclass  
Java_com_lsm_sociax_jni_1test_MainActivity_changeName(JNIEnv *env, jobject thiz) {//JNIEnv 是整个JNI的桥梁  
    //如果当前是native-lib.c  
    //(*env)->xxx函数 C是二级指针 C++是一级指针  
    //(*env)->DeleteLocalRef(env,null);//C是没有对象的,想持有env环境,必须包env传递进去  
    //String 对象引用 都是object  
    jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");  
    jfieldID nameFid = env->GetFieldID(mainActivityCls,"name","Ljava/lang/String;");//属性的签名 可以  
    jstring value = env->NewStringUTF("TimmyDuncan");  
    env->SetObjectField(thiz,nameFid,value);  
}extern "C"  
JNIEXPORT void JNICALL  
Java_com_lsm_sociax_jni_1test_MainActivity_changeAge(JNIEnv *env, jobject thiz) {  
    jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");  
  
    jfieldID ageFil = env->GetFieldID(mainActivityCls,"age","I");  
    env->SetIntField(thiz,ageFil,29);  
}

使用JNI 调用java方法

java代码:

class MainActivity : AppCompatActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
  
        // Example of a call to a native method  
        findViewById<TextView>(R.id.sample_text).text = stringFromJNI()  
        callAddMethod()  
    }  
  
    /**  
     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    external fun stringFromJNI(): String  
    external fun callAddMethod();//C 调用java方法--> add(ing number1,)  
  
    //被C调用的方法  
    public fun add(number1:Int,number2:Int):Int  
    {  
        return number1 + number2;  
    }    companion object {  
        // Used to load the 'native-lib' library on application startup.  
        init {  
            System.loadLibrary("native-lib")  
        }  
    }  
}

JNI代码:

#include <jni.h>  
#include <string>  
//日志输出  
#include <android/log.h>  
#define  TAG "Lsm"  
//__VA_ARGS__代表 ...可变参数  
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)  
extern "C" JNIEXPORT jstring JNICALL  
Java_com_lsm_sociax_jni_1test_MainActivity_stringFromJNI(  
        JNIEnv* env,  
        jobject /* this */) {  
    std::string hello = "Hello from C++";  
    return env->NewStringUTF(hello.c_str());  
}  
  
extern "C"//下面的代码采用C的编译方式,无论是C还是C++最终都是JNINativeInterface* 结构体  
JNIEXPORT //JNIEXPORT:JNI重要标记关键字,不能少,少了会报错/规则(标记为该方法可以被外部调用),为了统一Window版本,as可以因为android是linux  
void //void 代表java中的void  
JNICALL //也是一个关键字,(可以少的) jni call(约束函数入栈顺序和堆栈内存清理的规则  
//方法名 = 包名 +类名 + 方法  
// jobject 谁调用 谁的对象this 静态的话是jclass  
Java_com_lsm_sociax_jni_1test_MainActivity_changeName(JNIEnv *env, jobject thiz) {//JNIEnv 是整个JNI的桥梁  
    //如果当前是native-lib.c  
    //(*env)->xxx函数 C是二级指针 C++是一级指针  
    //(*env)->DeleteLocalRef(env,null);//C是没有对象的,想持有env环境,必须包env传递进去  
    //String 对象引用 都是object  
    jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");  
    jfieldID nameFid = env->GetFieldID(mainActivityCls,"name","Ljava/lang/String;");//属性的签名 可以  
    jstring value = env->NewStringUTF("TimmyDuncan");  
    env->SetObjectField(thiz,nameFid,value);  
} 
extern "C"  
JNIEXPORT void JNICALL  
Java_com_lsm_sociax_jni_1test_MainActivity_callAddMethod(JNIEnv *env, jobject thiz) {  
    jclass mainActivityCls = env->GetObjectClass(thiz);  
    jmethodID addMid = env->GetMethodID(mainActivityCls,"add","(II)I");  
   int result =  env->CallIntMethod(thiz,addMid,1,1);  
    LOGD("result:%d\n",result);  
}

JNI 接收 java传递过来的参数
  1. java层代码:
class MainActivity : AppCompatActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
        jniObj1()  
    }  
  
    /**  
     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    external fun stringFromJNI(): String  
    external fun jniObject(count:Int,textInfo:String,intList:IntArray,stringList:Array<String>)  
  
  
    companion object {  
        // Used to load the 'native-lib' library on application startup.  
        init {  
            System.loadLibrary("native-lib")  
        }  
    }  
  
    fun jniObj1(){  
        var listInt = intArrayOf(1,2,3,4,5)  
        var listString = arrayOf("lsm","yl","wy")  
        jniObject(3,"timmyDuncan",listInt,listString)  
        listInt.forEach { i ->  
            println("java经过C++修改的数组$i")  
        }  
    }  
}

2.JNI层的代码

#include <jni.h>  
#include <string>  
  
//日志输出  
#include <android/log.h>  
#define  TAG "Lsm"  
//__VA_ARGS__代表 ...可变参数  
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)  
  
extern "C" JNIEXPORT jstring JNICALL  
Java_com_lsm_sociax_jni_1test2_MainActivity_stringFromJNI(  
        JNIEnv *env,  
        jobject /* this */) {  
    std::string hello = "Hello from C++";  
    return env->NewStringUTF(hello.c_str());  
}extern "C"  
JNIEXPORT void JNICALL  
Java_com_lsm_sociax_jni_1test2_MainActivity_jniObject(JNIEnv *env, jobject thiz, jint count,  
                                                      jstring text_info, jintArray int_list,  
                                                      jobjectArray string_list) {  
    int _count = count;  
    LOGD("java传递进来的count是:%d\n",_count);  
    const char *_text_info = env->GetStringUTFChars(text_info, 0);//第二个参数是否需要Copy机制转换,这里不需要所以是0  
    LOGD("java传递进来的count是:%s\n",_text_info);  
    //C/C++用完是需要释放资源  
    env->ReleaseStringUTFChars(text_info,_text_info);  
    jint *_int_list = env->GetIntArrayElements(int_list,0);  
    int int_list_size = env->GetArrayLength(int_list);  
    for (int i = 0; i < int_list_size; ++i) {  
        LOGD("java传递进来的int数组是:%d\n",*(_int_list +i));  
        *(_int_list + i) = 1000 + i;  
        LOGD("java传递进来的int数组是:%d\n",*(_int_list +i));  
    }  
    /*  
     第三个参数mode的值:  
     JNI_OK 本次C++的修改的数组,刷新给JVM,java层,并且释放C++数组  
     JNI_COMMIT 本次C++的修改的数组,刷新给JVM,java层  
     JNI_ABORT 只释放C++数组  
     * */    env->ReleaseIntArrayElements(int_list,_int_list,JNI_OK);  
}

在JNI中创建JAVA对象,并调用对象的方法
  1. 两个实体类:
class Person {  
    private var student: Student? = null  
    fun setStudent(student: Student) {  
        println(  
            "java调用了Person的setStudent方法->name=${  
                student.name  
            }---age=${student.age}"  
        )  
        this.student = student  
    }  
  
    fun getStudent(): Student? {  
        return this.student  
    }  
}  
  
class Student {  
    var name: String? = null  
    var age: Int? = null  
  
    constructor(name: String?, age: Int?) {  
        this.name = name;  
        this.age = age  
    }  
}

  1. 在MainActivity中调用JNI方法
class MainActivity : AppCompatActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
  
        // Example of a call to a native method  
        findViewById<TextView>(R.id.sample_text).text = stringFromJNI()  
        newObjectPerson()  
    }  
  
    /**  
     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    external fun stringFromJNI(): String  
    external fun newObjectPerson()  
  
    companion object {  
        // Used to load the 'native-lib' library on application startup.  
        init {  
            System.loadLibrary("native-lib")  
        }  
    }  
}
  1. 在JNI中创建对象,并使用
#include <jni.h>  
#include <string>  
  
extern "C" JNIEXPORT jstring JNICALL  
Java_com_lsm_sociax_jni_1test3_MainActivity_stringFromJNI(  
        JNIEnv* env,  
        jobject /* this */) {  
    std::string hello = "Hello from C++";  
    return env->NewStringUTF(hello.c_str());  
}extern "C"  
JNIEXPORT void JNICALL  
Java_com_lsm_sociax_jni_1test3_MainActivity_newObjectPerson(JNIEnv *env, jobject thiz) {  
    jclass personClass = env->FindClass("com/lsm/sociax/jni_test3/Person");  
    jobject personObj = env->AllocObject(personClass);//C++分配一个对象出来,但不会调用构造函数  
    //env->NewObject() //C++实例化出一个对象,会调用构造函数  
    jmethodID setStudent = env->GetMethodID(personClass,"setStudent", "(Lcom/lsm/sociax/jni_test3/Student;)V");  
    //实例化Student类  
    jclass studentClass = env->FindClass("com/lsm/sociax/jni_test3/Student");  
    //Student类的构造方法  
    jmethodID studentInitMethod = env->GetMethodID(studentClass,"<init>", "(Ljava/lang/String;Ljava/lang/Integer;)V");  
    jstring  name = env->NewStringUTF("TimmyDuncan");  
  
    //创建一个Integer对象,kotlin int是一个对象  
    jclass intClass = env->FindClass("java/lang/Integer");  
    jmethodID intInit = env->GetMethodID(intClass,"<init>", "(I)V");  
    jobject intObj = env->NewObject(intClass,intInit,18);  
    //传承Student的对象  
    jobject studentObj = env->NewObject(studentClass,studentInitMethod,name,intObj);  
    env->DeleteLocalRef(intObj);  
    env->DeleteLocalRef(name);  
    //调用person的setStudent  
    env->CallVoidMethod(personObj,setStudent,studentObj);  
    //释放工作  
    env->DeleteLocalRef(personObj);  
    env->DeleteLocalRef(studentObj);//释放对象  
}
以上四个案例都是在AS运行中通过的
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值