随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

JNI中Kotlin和C++相互调用例子通解

一、概述

  案例:回顾JNI开发,主要回顾Java调用C/C++函数及C/C++调用Java类的方法

  1.JNI与Java数据类型对照表:

  

 

   

 

 

  2.JNI各种签名对照表:

  

 

 

 

二、Java和C/C++相互操作的示例代码

  1.定义一个Person.kt实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.yw.player.myjni
 
import android.util.Log
 
/**
 * 人
 */
class Person(
    var name: String? = "洛洛杨",
    var age: Int = 0
) {
 
    fun getPersonString(): String {
        return "$TAG $name | $age 岁"
    }
 
    companion object {
        val TAG = "YW_JNI_LOG"
        @JvmStatic//需要加上@JvmStatic不然jni中C++调用kotlin的静态方法会找不到方法名
        fun getPersonName(): String {
            return "洛洛杨"
        }
 
        @JvmStatic
        fun setPersonName(name: String) {
            Log.e("$TAG", name)
        }
    }
}

  2.定义一个调用C/C++方法的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
**
 * JNI测试工具类
 * 主要测试C++调用Java以及Java调用C++
 */
class MyJNI {
    /**
     * 操作单属性
     */
    external fun addPerson(name:String,age:Int)
 
    /**
     * 操作数组
     * @param names 小名和大名
     * @param ages 阴历和阳历
     */
    external fun optionArrays(names:Array<String>,ages:IntArray)
 
    /**
     * 操作直接传过去的对象
     */
    external fun addPerson(bean:Person)
 
 
    /**
     * 操作未传过去的对象
     */
    external fun optionObject()
}

  3.具体的调用类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jniBean = MyJNI()
        jniBean?.addPerson("洛洛杨,我儿子",4)
 
        var names = arrayOf<String>("洛洛杨","小洛洛")
        var ages = IntArray(2)
        ages[0] = 3
        ages[1] = 4
        jniBean?.optionArrays(names,ages)
 
        jniBean?.addPerson(Person().apply{
            name = "小洛洛小宝宝"
            age = 4;
        })
 
        jniBean?.optionObject()

  4.Java调用C/C++的具体实现方法及C/C+调用Java的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <jni.h>
#include <string>
#include <android/log.h>
 
#define TAG "YW_JNI_LOG" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型
 
 
 
/**
 * 操作普通内容
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_yw_player_myjni_MyJNI_addPerson__Ljava_lang_String_2I(JNIEnv *env, jobject thiz,
                                                               jstring name, jint age) {
    //获取从Java传递过来的String参数
    const char *c_name = env->GetStringUTFChars(name, 0);
    LOGE("用户名:%s", c_name);
 
    LOGE("年龄:%d", age);
 
    //释放String字符串
    env->ReleaseStringUTFChars(name, c_name);
}
 
 
/**
 * 操作数组
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_yw_player_myjni_MyJNI_optionArrays(JNIEnv *env, jobject thiz, jobjectArray names,
                                            jintArray ages) {
 
 
    int size = env->GetArrayLength(names);
    for (int i = 0; i < size; i++) {
        jstring name_index = static_cast<jstring>(env->GetObjectArrayElement(names, i));
        const char *c_name = env->GetStringUTFChars(name_index, NULL);
        LOGE("姓名:%s", c_name);
        env->ReleaseStringUTFChars(name_index, c_name);
    }
 
    jint *ages_arr = env->GetIntArrayElements(ages,NULL);
    int ageSize = env->GetArrayLength(ages);
    for (int i = 0; i < ageSize; i++) {
        LOGE("年龄:%d", *(ages_arr+i));
    }
 
}
 
 
 
/**
 * 在C++中操作java
 * 中的对象
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_yw_player_myjni_MyJNI_addPerson__Lcom_yw_player_myjni_Person_2(JNIEnv *env, jobject thiz,
                                                                        jobject bean) {
    //在C++中操作Java类
    //操作person中的方法
    jclass beanClass = env->GetObjectClass(bean);//获取字节码
    //获取对象方法
    jmethodID  getPersonStringId = env->GetMethodID(beanClass,"getPersonString",
                                                    "()Ljava/lang/String;");
    jstring returnStr = static_cast<jstring>(env->CallObjectMethod(bean,getPersonStringId));
    const char * c_str = env->GetStringUTFChars(returnStr,NULL);
    LOGE("返回的字符串为:%s",c_str);
    env->ReleaseStringUTFChars(returnStr,c_str);
 
    //操作对象的静态方法-->带返回值
    jmethodID staticMethodId = env->GetStaticMethodID(beanClass,"getPersonName","()Ljava/lang/String;");
    jstring static_name = static_cast<jstring>(env->CallStaticObjectMethod(beanClass,staticMethodId));
    const char * static_c_name = env->GetStringUTFChars(static_name,NULL);
    env->ReleaseStringUTFChars(static_name,static_c_name);
    LOGE("静态方法返回的姓名为:%s",static_c_name);
 
    //操作对象的静态方法,带参数
    jmethodID staticMethodId2 = env->GetStaticMethodID(beanClass,"setPersonName", "(Ljava/lang/String;)V");
    jstring str2 = env->NewStringUTF("老杨是洛洛杨的老爸");//需要new一个jstring字符串
    env->CallStaticVoidMethod(beanClass,staticMethodId2,str2);
 
    //操作属性
    jfieldID  fieldId = env->GetFieldID(beanClass,"name","Ljava/lang/String;");
    jstring fieldValue = env->NewStringUTF("洛洛杨小宝宝真是个小天才");
    env->SetObjectField(bean,fieldId,fieldValue);
    jstring fieldValue2 = static_cast<jstring>(env->GetObjectField(bean,fieldId));
    const char* c_fieldValue2 =  env->GetStringUTFChars(fieldValue2,NULL);
    LOGE("更改属性后的值:%s",c_fieldValue2);
}
 
/**
 * 操作未传过去的对象
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_yw_player_myjni_MyJNI_optionObject(JNIEnv *env, jobject thiz) {
    //创建一个java的class对象
    jclass beanClass = env->FindClass("com/yw/player/myjni/Person");
    LOGE("创建Class对象成功");
    //创建构造方法(构造函数需要传<init>)
    jmethodID constructorMethodId = env->GetMethodID(beanClass,"<init>","(Ljava/lang/String;I)V");
    jstring name = env->NewStringUTF("您好啊,洛洛杨小宝宝");
    LOGE("构造函数创建成功");
    //创建一个对象
    jobject  beanObject = env->NewObject(beanClass,constructorMethodId,name,4);
    LOGE("对象创建成功");
 
    //调用方法
    jmethodID getStringId = env->GetMethodID(beanClass,"getPersonString","()Ljava/lang/String;");
    jstring returnStr = static_cast<jstring>(env->CallObjectMethod(beanObject,getStringId));
    const char * returnStr_c = env->GetStringUTFChars(returnStr,NULL);
    LOGE("返回值的字符串为:%s",returnStr_c);
}

  

 

posted on   飘杨......  阅读(2065)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示