Kotlin开发jni程序 二.C调用java/kotlin方法和属性

本文详细介绍了在C语言中调用Kotlin静态和实例方法的步骤,包括如何通过JNI找到类、方法ID,调用方法及释放资源。涵盖了调用静态方法、实例方法和属性的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们声明kotlin的几个方法和属性,如下

package com.example.firstjni

import android.util.Log

object NDKUtil{
    val name = "djfklsd"
    external fun updateArray(array: IntArray)
    external fun updateArrayByPointer(array: IntArray)
    external fun callStaticMethod(i: Int)
    external fun callStaticMethod(i: Long)
    external fun callInstanceMethod(i: Int)
    external fun callInstanceMethod(s: String,i: Long)

    @JvmStatic
    fun callStaticJavaMethod(s: String?,i: Int){
        val len = s!!.length
        Log.i("native","c调用了java静态方法  $s  $i")

    }

    fun callJavaMethod(s: String,i: Int){
        Log.i("native","c调用了java方法  $s  $i")
    }
}

调用java或kotlin方法和属性基本步骤分4步
1.找到类,实例方法和属性要创建对象
2.找到方法或属性id
3.调用方法
4.释放资源

1.C调用kotlin静态方法
首先说一点,kotlin的object类和compaion object中,属性声明都是静态的,方法并不是静态,必须通过@JvmStatic注解,
方法才会声明为静态
在这里插入图片描述
可以看到kotlin反编译出的代码,只有@JvmStatic声明的方法才真正是静态方法,然后就可以在C中调用静态的方法

//1.首先要在C中获取jclass对象,也就是找到方法所在的类,通过完整  包名+类名
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");

/**2.找到该方法的方法ID
*参数一:jclass
*参数二:方法名
*参数三:方法签名
*方法签名,网上有详细说明,如果不想查,可以使用javap -s指令查询
*/
 jmethodID static_method_id = env->GetStaticMethodID(java_first, "callStaticJavaMethod",
                                                            "(Ljava/lang/String;I)V");

/**3.调用静态方法
*参数一:jclass
*参数二:方法ID
*参数三:参数三是可变长参数,也就是该方法声明时候对应的参数列表,相当于调用方法时的传参
*这个方法声明的是(s: String, i: Int)
*/
env->CallStaticVoidMethod(java_first, static_method_id, NULL, 2);

//4.删除掉本地引用
env->DeleteLocalRef(java_first);

javap命令查询
在这里插入图片描述
对于kotlin来说,先通过AS下面的Termial进入build\tmp\kotlin-classes\debug目录 调用javap -s 包名+类名,就会为你显示该类所有的方法签名,就是
descriptor:后面的部分 ,例如:()Ljava/lang/String;

2.调用实例方法
实例方法调用步骤类似,不过实例方法需要对象调用,而不能是直接通过类调用,需要先通过构造器创建对象

//1.找到类
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");```

//2.找到构造器方法,这个相当于查找无参构造器
jmethodID construct = env->GetMethodID(java_first, "<init>", "()V");

//3.创建对象
jobject NDKObj = env->NewObject(java_first, construct);

//4.再回到和静态调用差不多的步骤,找到目标方法
jmethodID jmethodID1 = env->GetMethodID(java_first, "callJavaMethod", "(Ljava/lang/String;I)V");

//5.通过对象调用方法,这个方法参数是(s: String, i: Int)
jstring message = env->NewStringUTF("调用成功了");
env->CallVoidMethod(NDKObj, jmethodID1, message, 1);

//6.释放资源
env->DeleteLocalRef(message);
env->DeleteLocalRef(NDKObj);

3.调用属性

//调用静态属性

//1.找类
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");

//2.找属性ID
jfieldID name_id = env->GetStaticFieldID(java_first, "name", "Ljava/lang/String;");

//3.获取属性,string类型是通过GetStaticObjectField,其他的属性都有对应的方法,比如对于Int 就是GetStaticIntField
jstring name_obj = (jstring) env->GetStaticObjectField(java_first, name_id);

//至于实例属性,和调用实例方法步骤差不多,这里不多赘述

NOTE:查找方法和属性ID的时候,方法签名有多个参数,要用;隔开,如果只有一个参数,结尾也要用;

plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) //kotlin("kapt") // 关键:添加 KAPT 插件//id 'kotlin-kapt' // 必须添加此插件 // 新版可能需要的声明方式 //alias(libs.plugins.kotlin.kapt) id("com.google.devtools.ksp") version "2.0.21-1.0.27" // 使用最新兼容版本 } android { namespace = "com.cmcc.ops" compileSdk = 35 sourceSets { getByName("main") { // ✅ 正确写法 1 //jniLibs.srcDirs = listOf("src/main/jniLibs") // ✅ 正确写法 2 jniLibs.setSrcDirs(listOf("src/main/jniLibs")) } named("debug") { jniLibs.srcDirs("src/debug/jniLibs") // ✅ 直接调用方法 } } defaultConfig { applicationId = "com.cmcc.ops" minSdk = 24 targetSdk = 35 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" // NDK 配置 ndk { // 明确指定只包含 arm64 armeabi abiFilters.set(listOf("arm64-v8a", "armeabi-v7a")) } } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } buildFeatures { //dataBinding = true viewBinding = true // 可共存 } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = "11" } } dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) implementation(libs.androidx.datastore.core.android) implementation(libs.androidx.datastore.preferences) // DataStore 依赖 implementation (libs.androidx.lifecycle.viewmodel.ktx) // ViewModel 核心库 implementation(libs.material) implementation(libs.okhttp) // 最新稳定版 implementation(libs.logging.interceptor) // 日志拦截器 implementation(libs.org.jetbrains.kotlinx.kotlinx.coroutines.android3) // 协程支持 implementation(libs.json) // 使用Android自带org.json库 implementation(libs.gson) implementation(libs.baselibrary) implementation(libs.androidx.databinding.runtime) implementation(libs.androidx.junit.ktx) testImplementation(libs.junit) androidTestImplementation(libs.androidx.espresso.core) add("ksp", "androidx.room:room-compiler:2.6.1") //ksp ("androidx.room:room-compiler:2.6.1") // 示例:Room 注解处理器 implementation (libs.dagger) //kapt (libs.dagger.compiler) // 正确写法(使用AndroidX版本) //implementation 'androidx.appcompat:appcompat:1.6.1' //implementation ("androidx.constraintlayout:constraintlayout:2.1.4") } e: file:///E:/workspace/Android/MyApplication/app/build.gradle.kts:40:24: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public inline operator fun kotlin.text.StringBuilder /* = java.lang.StringBuilder */.set(index: Int, value: Char): Unit defined in kotlin.text
03-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值