Interop: rework String auto conversion

use memScoped
This commit is contained in:
Svyatoslav Scherbina
2016-10-19 15:59:55 +03:00
parent 53884f8da6
commit 8a66de216d
2 changed files with 25 additions and 24 deletions
@@ -32,13 +32,15 @@ fun Placement.allocNativeArrayOf(elements: ByteArray): NativeArray<Int8Box> {
}
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<Int8Box>.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
@@ -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<Type>) =