Native-Kommons is a powerful Kotlin Multiplatform library designed to simplify and unify JNI (Java Native Interface) development across Android, Desktop (Linux, macOS, Windows), and Kotlin/Native.
It provides a common JNI interface for all supported native targets and includes a KSP module to automatically generate JNI-compatible function stubs, eliminating boilerplate and bridging the gap between your native Kotlin code and the Java world.
- Unified JNI API: Write common JNI code for
androidNative,linux,macos, andmingwX64targets. - Type Conversion Utilities: A rich set of extension functions to effortlessly convert between JNI types and standard Kotlin types (e.g.,
jstring.toKString(),IntArray.toJIntArray()). - KSP Code Generation: Automatically generate JNI-compatible C-style function stubs from your idiomatic Kotlin functions using the
@JNIConnectannotation. - Seamless Java Integration: Call your native Kotlin functions directly from Java with standard Kotlin types, just as you would with any other external method.
I'm putting this here because I'm getting ripped off by the german BAföG Amt 🖕🏻 and other german government offices. 😃
Important
I’m a creator and maintainer of multiple open-source projects, especially in the Kotlin Multiplatform world, which take a lot of time, energy, and coffee to keep going :)
If my work has helped you or your team, please consider sponsoring me to help keep these projects alive and thriving.
Your support means I can spend more time building and improving tools for the community.
To use Native-Kommons in your project, add the dependencies to your build.gradle.kts file.
Using the common JNI library is fairly easy, just add the dependency for your native targets.
kotlin {
/* --- BEGINNING OF SUPPORTED TARGETS --- */
androidNativeX64()
androidNativeArm64()
androidNativeX86()
androidNativeArm32()
linuxX64()
linuxArm64()
mingwX64()
macosX64()
macosArm64()
/* --- ENDING OF SUPPORTED TARGETS --- */
sourceSets {
val nativeMain by getting {
dependencies {
// Add the core JNI utilities
implementation("dev.datlag.nkommons:jni:<version>")
}
}
}
}Using the KSP module to auto-generate JNI-compatible function stubs can be easily done as well.
First ensure your project is configured for using KSP.
plugins {
id("com.google.devtools.ksp")
}Then add the KSP processor and annotations to your module's dependencies
kotlin {
sourceSets {
val nativeMain by getting {
dependencies {
// Add the annotations dependency for KSP
implementation("dev.datlag.nkommons:annotations:<version>")
}
}
}
}
dependencies {
ksp("dev.datlag.nkommons:ksp:<version>")
}Native-Kommons offers two main features that can be used together or independently: JNI Utilities and the @JNIConnect Annotation Processor.
The library provides a set of handy extension functions to make conversions between JNI and Kotlin types trivial.
Simply import the functions you need and call them on the respective types. The JNIEnv pointer is required for operations that interact with the JVM.
import dev.datlag.nkommons.utils.*
import dev.datlag.nkommons.JNIEnvVar
import dev.datlag.nkommons.binding.jstring
import kotlinx.cinterop.CPointer
@CName("Java_your_package_name_ClassName_printMessage")
fun printMessage(env: CPointer<JNIEnvVar>, clazz: jobject, message: jstring) {
val kotlinString: String? = message.toKString(env)
println("Message from Java: $kotlinString")
}The @JNIConnect annotation is the core of the KSP module. It generates the necessary JNI boilerplate so you can write clean, idiomatic Kotlin code.
Write your function using standard Kotlin types and annotate it with @JNIConnect.
import dev.datlag.nkommons.JNIConnect
import dev.datlag.nkommons.JNIPackageName
import dev.datlag.nkommons.JNIClassName
import dev.datlag.nkommons.JNIFunctionName
@JNIConnect
@JNIPackageName("your.package.name")
@JNIClassName("YourClass")
@JNIFunctionName("customFunction")
fun example(a: String, b: Boolean, c: CharArray, d: Double): String {
return "$a, $b, $c, $d"
}Warning
The provided @JNIPackageName, @JNIClassName and @JNIFunctionName annotations will be removed.
Their parameters will be merged into @JNIConnect.
Waiting for KSP fix: google/ksp#2356
When you build the project, KSP will automatically generate a JNI-compatible function. You don't need to touch this generated file.
Now, you can declare and call the original function in your Java or JVM Kotlin code as if it were a simple external method.
package your.package.name
object YourClass {
// same signature as native
external fun customFunction(a: String, b: Boolean, c: CharArray, d: Double): String
}Following types are currently supported for the auto generation:
| Type | ArrayType |
|---|---|
| Boolean | BooleanArray |
| Byte | ByteArray |
| Char | CharArray |
| Double | DoubleArray |
| Float | FloatArray |
| Int | IntArray |
| Long | LongArray |
| Short | ShortArray |
| String |