kotlin-native05 进行JNI开发

介绍

在网上看到一篇文章: 用 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, 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, 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代码


    执行结果

参考链接

  • 用 Kotlin Native 写 Jni,以后写 Android 基本上要没有别的语言什么事儿了的节奏
  • Building Multiplatform Projects with Gradlel

你可能感兴趣的:(kotlin-native05 进行JNI开发)