介绍
在网上看到一篇文章: 用 Kotlin Native 写 Jni,以后写 Android 基本上要没有别的语言什么事儿了的节奏,卓的JNI环境好像是自动配置,这里来介绍一下非安卓环境的kotlin-native JNI开发的环境配置。
环境配置
- 准备java类
package cn.hohov.demo;
public class KotlinDLLDemo {
static {
System.load("D:\\Workplace\\Clion\\kotlin-jni\\build\\bin\\Dll\\jniDllReleaseShared\\jniDll.dll");
}
public native String nativeString();
public String sayHi() {
return "str from java";
}
public static void main(String[] args) {
KotlinDLLDemo demo = new KotlinDLLDemo();
System.out.println(demo.nativeString());
}
}
-
新建空的kotlin-native项目,创建gradle的脚本文件和def文件
build.gradle.kts
plugins {
kotlin("multiplatform") version "1.3.41"
}
repositories {
mavenCentral()
}
kotlin {
mingwX64("Dll") {
compilations.getByName("main") {
val jni by cinterops.creating {
// def文件路径
defFile(project.file("def/jni.def"))
// def生成的kotin库包名
packageName("jni")
// jni所需头文件的路径
includeDirs("C:\\Program Files\\Java\\jdk1.8.0_191\\include",
"C:\\Program Files\\Java\\jdk1.8.0_191\\include\\win32")
}
}
binaries {
sharedLib("jniDll") {
baseName = "jniDll"
}
}
}
}
headers = jni.h
项目结构
-
执行cinteropJniKotlin-jni
gradle interop -
生成的包,现在可以带着Clion的提示进行开发了
jni lib
开始jni开发
java调用jni
- 在jni.kt写入如下代码,@CName表示到处的C函数的名字,为了jni能找到对应的函数,格式是
Java_包名_类名_方法名
package cn.hohov.jni
import jni.JNIEnvVar
import jni.jobject
import jni.jstring
import kotlinx.cinterop.*
@CName("Java_cn_hohov_demo_KotlinDLLDemo_nativeString")
fun stringFromJNI(env: CPointer<JNIEnvVar>, thiz: jobject): jstring {
memScoped {
return env.pointed.pointed!!.NewStringUTF!!.invoke(env, "This is from Kotlin Native!!".cstr.ptr)!!
}
}
-
编译项目,生成dll
jniDll.dll -
接下来执行之前的java代码KotlinDLLDemo.class
执行结果
jni中调用java方法
- 修改jni.kt的代码
package cn.hohov.jni
import jni.JNIEnvVar
import jni.jobject
import jni.jstring
import kotlinx.cinterop.*
@CName("Java_cn_hohov_demo_KotlinDLLDemo_nativeString")
fun stringFromJNI(env: CPointer<JNIEnvVar>, thiz: jobject): jstring {
memScoped {
val jniEnvVal = env.pointed.pointed!!
val jclass = jniEnvVal.GetObjectClass!!.invoke(env, thiz)
// 获取sayHi静态方法
val methodId = jniEnvVal.GetMethodID!!.invoke(env, jclass, "sayHi".cstr.ptr, "()Ljava/lang/String;".cstr.ptr)
print("In Kotlin Native: ")
// 调用sayHi方法
val jStrFromJava = jniEnvVal.CallObjectMethodA!!.invoke(env, thiz, methodId, null) as jstring
// 将jstring转换为kotlin中的string
val stringFromJava = jniEnvVal.GetStringChars!!.invoke(env, jStrFromJava, null)!!.toKString()
println(stringFromJava)
return env.pointed.pointed!!.NewStringUTF!!.invoke(env, "This is from Kotlin Native!!".cstr.ptr)!!
}
}
-
build,然后执行java代码
执行结果
网友评论