From 8a66de216d9af51485fa4cfd5bb12f05c6d00df5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 19 Oct 2016 15:59:55 +0300 Subject: [PATCH] Interop: rework String auto conversion use memScoped --- .../kotlin/kotlin_native/interop/Utils.kt | 16 ++++----- .../native/interop/gen/jvm/StubGenerator.kt | 33 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Interop/Runtime/src/main/kotlin/kotlin_native/interop/Utils.kt b/Interop/Runtime/src/main/kotlin/kotlin_native/interop/Utils.kt index ae0f1f701fb..b5c9c5bc373 100644 --- a/Interop/Runtime/src/main/kotlin/kotlin_native/interop/Utils.kt +++ b/Interop/Runtime/src/main/kotlin/kotlin_native/interop/Utils.kt @@ -32,13 +32,15 @@ fun Placement.allocNativeArrayOf(elements: ByteArray): NativeArray { } fun CString.Companion.fromString(str: String?): CString? { - if (str == null) { - return null - } + return str?.toCString(heap) +} - val bytes = str.toByteArray() // TODO: encoding +fun Int8Box.asCString() = CString.fromArray(NativeArray.byRefToFirstElem(this, Int8Box)) + +fun String.toCString(retValPlacement: Placement): CString { + val bytes = this.toByteArray() // TODO: encoding val len = bytes.size - val nativeBytes = malloc(NativeArray of Int8Box length (len + 1)) + val nativeBytes = retValPlacement.alloc(array[len + 1](Int8Box)) bytes.forEachIndexed { i, byte -> nativeBytes[i].value = byte @@ -48,10 +50,6 @@ fun CString.Companion.fromString(str: String?): CString? { return CString.fromArray(nativeBytes) } -fun NativeArray.asCString() = CString.fromArray(this) -fun Int8Box.asCString() = CString.fromArray(NativeArray.byRefToFirstElem(this, Int8Box)) -fun String.toCString() = CString.fromString(this) - class MemScope private constructor(private val arena: Arena) : Placement by arena { val memScope: Placement get() = this diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt index 40606e6cb9b..054f54db7d3 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt @@ -229,12 +229,12 @@ class StubGenerator( * * @param kotlinType the name of Kotlin type to be used for this value in Kotlin. * @param kotlinConv the function such that `kotlinConv(name)` converts variable `name` to pass it into JNI stub - * @param convFree the function such that `convFree(name)` is the statement that frees the result of conversion + * @param memScoped the conversion allocates memory and should be placed into `memScoped {}` block * @param kotlinJniBridgeType the name of Kotlin type to be used for this value in JNI stub */ class OutValueBinding(val kotlinType: String, val kotlinConv: ((String) -> String)? = null, - val convFree: ((String) -> String)? = null, + val memScoped: Boolean = false, val kotlinJniBridgeType: String = kotlinType) /** @@ -312,8 +312,8 @@ class StubGenerator( ) is Int8Type -> return OutValueBinding( kotlinType = "String?", - kotlinConv = { name -> "CString.fromString($name).getNativePtr().asLong()" }, - convFree = { name -> "free(NativePtr.byValue($name))" }, + kotlinConv = { name -> "$name?.toCString(memScope).getNativePtr().asLong()" }, + memScoped = true, kotlinJniBridgeType = "Long" ) } @@ -564,8 +564,9 @@ class StubGenerator( "$name: " + paramBindings[i].kotlinType }.joinToString(", ") - out("fun ${func.name}($args): ${retValBinding.kotlinType} {") - indent { + val header = "fun ${func.name}($args): ${retValBinding.kotlinType}" + + fun generateBody() { val externalParamNames = paramNames.mapIndexed { i: Int, name: String -> val binding = paramBindings[i] val externalParamName: String @@ -581,13 +582,6 @@ class StubGenerator( } out("val res = externals.${func.name}(" + externalParamNames.joinToString(", ") + ")") - paramNames.forEachIndexed { i, name -> - val binding = paramBindings[i] - if (binding.convFree != null) { - assert(binding.kotlinConv != null) - out(binding.convFree.invoke(externalParamNames[i])) - } - } if (dumpShims) { val returnValueRepresentation = retValBinding.conv("res") @@ -599,9 +593,18 @@ class StubGenerator( } out("return " + retValBinding.conv("res")) - } - out("}") + + block(header) { + val memScoped = paramBindings.any { it.memScoped } + if (memScoped) { + block("memScoped") { + generateBody() + } + } else { + generateBody() + } + } } private fun getFfiStructType(elementTypes: List) =