Skip to content

DatL4g/Native-Kommons

Repository files navigation

Native-Kommons ネイティフ・コモンズ

Kotlin Multiplatform Android Native Linux MacOS Windows Language licence github stars Build

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.

✨ Features

  • Unified JNI API: Write common JNI code for androidNative, linux, macos, and mingwX64 targets.
  • 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 @JNIConnect annotation.
  • Seamless Java Integration: Call your native Kotlin functions directly from Java with standard Kotlin types, just as you would with any other external method.

💖 Support my work

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.

🛠️ Setup

To use Native-Kommons in your project, add the dependencies to your build.gradle.kts file.

Java Native Interface

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>")
            }
        }
    }
}

KSP

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>")
}

Usage

Native-Kommons offers two main features that can be used together or independently: JNI Utilities and the @JNIConnect Annotation Processor.

JNI Utilities

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.

Example: Converting jstring to a Kotlin String

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")
}

KSP Auto-Generating JNI Stubs with @JNIConnect

The @JNIConnect annotation is the core of the KSP module. It generates the necessary JNI boilerplate so you can write clean, idiomatic Kotlin code.

1. Write Your Kotlin/Native Function

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

2. Let KSP generate the JNI Stub

When you build the project, KSP will automatically generate a JNI-compatible function. You don't need to touch this generated file.

3. Declare and Use in JVM

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
}

Supported Types

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

About

Common types and methods for Kotlin native

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published

Languages