Nucleus Native Access¶
Every now and then, no runtime library covers your exact native API need. Nucleus handles the common cases with JNI — but when you need something specific (a platform API, a custom algorithm, a C library), the usual path involves writing JNI glue in C, building a .so/.dylib/.dll, bundling it, and wiring it up from Kotlin. That's a lot of friction for what should be a simple call.
Nucleus Native Access removes that friction. Write your native logic in Kotlin/Native, and the plugin generates the FFM bridge automatically. No C, no build scripts, no manual JNI plumbing — just Kotlin on both sides.
FFM, not JNI
Nucleus's built-in runtime libraries (decorated windows, dark mode, notifications…) use JNI for broad compatibility. Nucleus Native Access uses the Foreign Function & Memory (FFM) API (JEP 454, stable since JDK 22). Both are valid approaches, but FFM lets you write the native side in pure Kotlin rather than C.
How It Works¶
flowchart TB
A["Your Kotlin/Native code"] --> B["Gradle plugin"]
B --> C["Your JVM code calls it like normal Kotlin"]
B@{ shape: rect }
The plugin:
- Analyzes sources via Kotlin PSI
- Generates
@CNamebridge functions (native side) - Generates FFM
MethodHandleproxies (JVM side) - Compiles to
.so/.dylib/.dll - Bundles into JAR under
kne/native/{os}-{arch}/
The generated JVM proxies have the exact same API as your native classes — same names, same types, same method signatures. No wrapper types, no casting, no boilerplate.
Setup¶
Separate versioning
Nucleus Native Access is versioned independently from Nucleus. Check the latest version on the NucleusNativeAccess repository.
Add the plugin to your Kotlin Multiplatform module:
// build.gradle.kts
plugins {
kotlin("multiplatform")
id("io.github.kdroidfilter.nucleusnativeaccess") version "<version>" // see github.com/kdroidFilter/NucleusNativeAccess
}
kotlin {
jvmToolchain(25) // FFM requires JDK 22+; JDK 25 recommended
macosArm64() // or macosX64(), linuxX64(), mingwX64()
jvm()
}
kotlinNativeExport {
nativeLibName = "mylib"
nativePackage = "com.example.mylib"
}
That's the entire configuration. The plugin handles compilation, bundling, and loading automatically.
JDK requirement
FFM is stable from JDK 22+. JDK 25 is recommended. When running tests or the app, the JVM arg --enable-native-access=ALL-UNNAMED is required — the plugin adds it automatically for tests.
Using with Compose Desktop¶
The Compose compiler plugin doesn't support arbitrary Kotlin/Native targets (e.g. linuxX64, mingwX64) used for FFM bridges. Put your native code in a separate Gradle module without the Compose compiler plugin:
my-app/
├── native/ ← Kotlin/Native + nucleusnativeaccess (no Compose)
│ └── build.gradle.kts
├── app/ ← Compose Desktop + Nucleus, depends on :native
│ └── build.gradle.kts
└── settings.gradle.kts
:native/build.gradle.kts:
plugins {
kotlin("multiplatform")
id("io.github.kdroidfilter.nucleusnativeaccess") version "<version>"
}
kotlin {
jvmToolchain(25)
linuxX64() // or macosArm64(), mingwX64()
jvm()
}
kotlinNativeExport {
nativeLibName = "mylib"
nativePackage = "com.example.mylib"
}
:app/build.gradle.kts:
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose")
id("io.github.kdroidfilter.nucleus")
}
kotlin {
jvmToolchain(25)
jvm()
sourceSets {
val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
implementation(project(":native"))
}
}
}
}
nucleus.application {
mainClass = "com.example.MainKt"
jvmArgs += listOf("--enable-native-access=ALL-UNNAMED")
}
GraalVM Native Image¶
Nucleus Native Access includes full GraalVM metadata generation:
reflect-config.jsonfor all generated proxy classesresource-config.jsonfor bundled native librariesreachability-metadata.jsonfor FFM descriptors
No manual configuration needed — the generated metadata is picked up automatically by the Nucleus GraalVM plugin.
Repository¶
Nucleus Native Access is maintained in a separate repository with its own release cycle:
kdroidFilter/NucleusNativeAccess — plugin source, examples, full documentation, and latest releases.
The plugin ID is io.github.kdroidfilter.nucleusnativeaccess.
Next steps¶
- Supported Types — Full type mapping reference, declarations, and current limitations
- Usage & Patterns — Real-world examples, coroutines, flows, object lifecycle