Exploring Kotlin Multiplatform: Native Interop, Logging, IO, and SQLite Scenarios
This article examines Kotlin Multiplatform's evolution, detailing native compilation, cinterop bindings, platform libraries, bidirectional Swift/Objective‑C interop, and practical cross‑platform implementations for logging, file I/O, and SQLite, while outlining future directions and tooling recommendations.
Author Chen Qi, Ctrip ticket R&D director, describes the transition from native to Ctrip React Native and the need for cross‑platform solutions beyond UI frameworks.
Native multiplatform solutions traditionally rely on C/C++; Kotlin Multiplatform (KMP) offers a modern alternative with Kotlin/Native compiling to native binaries via LLVM.
Kotlin/Native supports iOS, macOS, Android, Windows, Linux, WebAssembly and provides tools like cinterop to generate bindings to C libraries.
cinterop uses .def files to describe C APIs and produces Kotlin types, functions and constants, resulting in .kexe executables or .klib libraries.
Kotlin/Native supplies platform libraries for POSIX, Win32, Apple frameworks, OpenGL, zlib, etc., located in the ~/.konan directory.
Bidirectional interop with Swift/Objective‑C is possible through cinterop, allowing Kotlin code to call os_log and other native APIs.
Kotlin Multiplatform redesign (Kotlin 1.3) unifies project structure, making Kotlin/Native a target platform and simplifying Gradle plugin usage.
Scenario 1 – Logger: demonstrates Java Logger, Android Log, iOS os_log, and a common Kotlin expect/actual logging API with platform‑specific implementations.
import java.util.logging.Logger
private val logger = Logger.getLogger("Module")
fun javaLog() {
logger.fine("Fine Msg")
logger.config("Config Msg")
logger.info("Info Msg")
logger.warning("Warning Msg")
logger.severe("Error Msg")
} import android.util.Log
private val tag = "Module"
fun androidLog() {
Log.v(tag, "Verbose Msg")
Log.d(tag, "Debug Msg")
Log.i(tag, "Info Msg")
Log.w(tag, "Warning Msg")
Log.e(tag, "Error Msg")
} void iOSLog() {
os_log(OS_LOG_DEFAULT, "Msg");
os_log_fault(OS_LOG_DEFAULT, "Fault Msg");
os_log_error(OS_LOG_DEFAULT, "Error Msg");
os_log_info(OS_LOG_DEFAULT, "Info Msg");
os_log_debug(OS_LOG_DEFAULT, "Debug Msg");
os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, "Msg with type");
} /**
* Keep consistent with android.util.log constant level.
*/
enum class Level(val value: Int) {
VERBOSE(2), DEBUG(3), INFO(4), WARN(5), ERROR(6), ASSERT(7)
}
expect object Log {
fun isLoggable(tag: String, level: Level): Boolean
fun v(tag: String, msg: String)
fun d(tag: String, msg: String)
fun i(tag: String, msg: String)
fun w(tag: String, msg: String)
fun e(tag: String, msg: String)
fun wtf(tag: String, msg: String)
} // Kotlin Android Implementation
actual object Log {
actual fun isLoggable(tag: String, level: Level): Boolean = android.util.Log.isLoggable(tag, level.value)
actual fun v(tag: String, msg: String) { android.util.Log.v(tag, msg) }
actual fun d(tag: String, msg: String) { android.util.Log.d(tag, msg) }
actual fun i(tag: String, msg: String) { android.util.Log.i(tag, msg) }
actual fun w(tag: String, msg: String) { android.util.Log.w(tag, msg) }
actual fun e(tag: String, msg: String) { android.util.Log.e(tag, msg) }
actual fun wtf(tag: String, msg: String) { android.util.Log.wtf(tag, msg) }
} // Kotlin iOS Implementation
import kotlinx.cinterop.ptr
import platform.darwin.*
actual object Log {
actual fun isLoggable(tag: String, level: Level): Boolean =
os_log_type_enabled(OS_LOG_DEFAULT, level.toPlatform())
actual fun v(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, "$tag | $msg")
actual fun d(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "$tag | $msg")
actual fun i(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_INFO, "$tag | $msg")
actual fun w(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_INFO, "$tag | $msg")
actual fun e(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, "$tag | $msg")
actual fun wtf(tag: String, msg: String) =
_os_log_internal(__dso_handle.ptr, OS_LOG_DEFAULT, OS_LOG_TYPE_FAULT, "$tag | $msg")
} // Kotlin AndroidNativeArm Implementation
import platform.android.*
actual object Log {
actual fun isLoggable(tag: String, level: Level): Boolean = level >= Level.INFO
actual fun v(tag: String, msg: String) { __android_log_write(ANDROID_LOG_VERBOSE.toInt(), tag, msg) }
actual fun d(tag: String, msg: String) { __android_log_write(ANDROID_LOG_DEBUG.toInt(), tag, msg) }
actual fun i(tag: String, msg: String) { __android_log_write(ANDROID_LOG_INFO.toInt(), tag, msg) }
actual fun w(tag: String, msg: String) { __android_log_write(ANDROID_LOG_WARN.toInt(), tag, msg) }
actual fun e(tag: String, msg: String) { __android_log_write(ANDROID_LOG_ERROR.toInt(), tag, msg) }
actual fun wtf(tag: String, msg: String) { __android_log_write(ANDROID_LOG_FATAL.toInt(), tag, msg) }
}Scenario 2 – IO File: compares Java IO/NIO/NIO2 on Android/JVM with POSIX file APIs on iOS, showing a Kotlin/Native file‑reading example using fopen , fgets , and memScoped for automatic memory management.
fun sample() {
val file = fopen(__filename = "filename", __mode = "r")
if (file != null) {
try {
memScoped {
val bufferLength = 1024
val buffer = allocArray
(bufferLength)
while (true) {
val line = fgets(buffer, bufferLength, file)?.toKString()
if (line == null || line.isEmpty()) break
println(line)
}
}
} finally {
fclose(file)
}
}
}Scenario 3 – SQLite: surveys Android SQLiteOpenHelper, Jetpack Room, iOS SQLite libraries, and highlights SQLDelight as a mature Kotlin Multiplatform SQLite solution that generates type‑safe Kotlin code from SQL statements.
The future of Kotlin includes continued stability improvements, the Moving Fast (MF) stage for multiplatform projects, and growing adoption in Android Jetpack, Square's Okio 2, OkHttp 4.0, and other libraries.
Additional notes cover Gradle Kotlin DSL migration (KTS) and provide links to official documentation and related reading.
Ctrip Technology
Official Ctrip Technology account, sharing and discussing growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.