EXPERIMENT for providing Kotlin Multiplatform Foreign Function Interface
Support for all kotlin platforms:
- JVM
- via JNI: min JDK 8
- via FFM(Panama): min JDK 20 (JEP: https://openjdk.org/jeps/434)
- Android via JNI (minSdk 21)
- Native via cinterop
- WASM via emscripten
- JS via emscripten
- ffi-c-runtime - kotlinx.cinterop package adapted for multiplatform
- libraries
- libcrypto3
- api - expect/actual declarations for some part of OpenSSL libcrypto API
- shared - dynamically linked artifacts - only native and jvm desktop targets
- prebuilt - library is embedded and no additional configuration is needed
- test - some basic tests which tests, that everything REALLY works
- libcrypto3
For future auto-generated bindings we need to keep in mind platform details
Uses similar code, that could generate jextract but using some kotlin specifics. Only Kotlin codegen and JDK 20 is needed.
Uses similar code, that is used in K/N jvm cinterop flavor. To use such bindings we need:
- generate Kotlin code
- generate C code
- build JNI C library using some compiler for each OS (not sure, what is the best workflow here regarding portability and cross-compilation)
- somehow package it - both per OS ARCH and single artifact for all OSs
For Android everything is the same but building and packaging is not a problem as NDK is able to cross-compile and AAR format supports distributing shared libraries for multiple architectures
TODO:
- requires compiler to build JNI library - how to set up it properly to support different OSs?
- is it possible to use K/N provided clang with cross-compile possibilities here?
- replace ByteBuffers with Unsafe but with safe fallback to ByteBuffers if Unsafe is not available (similar to how netty handles it)
- somehow fix duplicating service in resources for android
Uses emscripten to generate WASM binary from C library To use such bindings we need:
- generate Kotlin code
- generate C code
- build WASM binary using emscripten (
emcc
can be run on any supported OS) - somehow package it (still not sure how)
TODO:
- how to set up packaging, so it will work all time?
- JS uses hardcoded emscripten library name in external declarations - how to avoid it?
- how to support memory sharing between different libraries?
- how to publish wasm js with kotlin library, so it will be consumable?
- a lot of hacks to attach prebuilt dependency...
- setup testing in browser
- WASM for now require JS to launch, need to support WASI in future somehow
Nothing interesting, just mapping for cinterop
TBD - a lot of work is needed here. As first step, the idea is using original cinterop to generate declarations for clang index for some K/N target, write minimal generator that will work for libcrypto3 sample and clang index. Then generate declarations and continue work with JVM (faster dev cycle) while still using common code (at least to be able to run it later in K/N - why? just why not)
- integration with https://conan.io for providing/building native libraries