From ec8405918378213a0e64cc0b3605ac3329fb903b Mon Sep 17 00:00:00 2001 From: "dima.avdeev" Date: Fri, 10 Nov 2023 22:52:41 +0400 Subject: [PATCH] Fix problem with conversion of Kotlin String to C char * (#827) --- skiko/RELEASE.md | 1 + .../org/jetbrains/skia/impl/Native.native.kt | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/skiko/RELEASE.md b/skiko/RELEASE.md index 91be26906..60d522e11 100644 --- a/skiko/RELEASE.md +++ b/skiko/RELEASE.md @@ -21,6 +21,7 @@ build configuration. ```bash ./gradlew publishToMavenLocal -Pskiko.native.enabled=true -Pskiko.wasm.enabled=true -Pskiko.android.enabled=true ``` +Use flag `-Pskiko.debug=true` to build with debug build type. ##### Publish to `build/repo` directory ```bash diff --git a/skiko/src/nativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt b/skiko/src/nativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt index 859061532..ffd54ae11 100644 --- a/skiko/src/nativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt +++ b/skiko/src/nativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt @@ -66,10 +66,7 @@ internal actual inline fun interopScope(block: InteropScope.() -> T): T { internal actual class InteropScope actual constructor() { actual fun toInterop(string: String?): InteropPointer { return if (string != null) { - // encodeToByteArray encodes to utf8 - val utf8 = string.encodeToByteArray() - // TODO Remove array copy, use `skString(data, length)` instead of `skString(data)` - val pinned = utf8.copyOf(utf8.size + 1).pin() + val pinned = convertToZeroTerminatedString(string).pin() elements.add(pinned) val result = pinned.addressOf(0).rawValue result @@ -186,7 +183,7 @@ internal actual class InteropScope actual constructor() { if (stringArray == null || stringArray.isEmpty()) return NativePtr.NULL val pins = stringArray.toList() - .map { it.encodeToByteArray().pin() } + .map { convertToZeroTerminatedString(it).pin() } val nativePointerArray = NativePointerArray(stringArray.size) pins.forEachIndexed { index, pin -> @@ -284,3 +281,14 @@ private external fun initCallbacks( callVoid: COpaquePointer, dispose: COpaquePointer ) + +/** + * Converts String to zero-terminated utf-8 byte array. + */ +private fun convertToZeroTerminatedString(string: String): ByteArray { + // C++ needs char* with zero byte at the end. So we need to copy array with an extra zero byte. + + val utf8 = string.encodeToByteArray() // encodeToByteArray encodes to utf8 + // TODO Remove array copy, use `skString(data, length)` instead of `skString(data)` + return utf8.copyOf(utf8.size + 1) +}