Minorly rework CValuesRef to make it more universal when subclassing
Allow `getPointer` to register custom disposers with `defer`
This commit is contained in:
committed by
SvyatoslavScherbina
parent
a3721f857c
commit
17ccd3ee02
+3
-3
@@ -184,9 +184,9 @@ internal fun CValue<CXCursor>.isLeaf(): Boolean {
|
||||
return !hasChildren
|
||||
}
|
||||
|
||||
internal fun List<String>.toNativeStringArray(placement: NativePlacement): CArrayPointer<CPointerVar<ByteVar>> {
|
||||
return placement.allocArray(this.size) { index ->
|
||||
this.value = this@toNativeStringArray[index].cstr.getPointer(placement)
|
||||
internal fun List<String>.toNativeStringArray(scope: AutofreeScope): CArrayPointer<CPointerVar<ByteVar>> {
|
||||
return scope.allocArray(this.size) { index ->
|
||||
this.value = this@toNativeStringArray[index].cstr.getPointer(scope)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,26 +70,7 @@ abstract class CValuesRef<T : CPointed> {
|
||||
* If this reference is [CPointer], returns this pointer.
|
||||
* Otherwise copies the referenced values to [placement] and returns the pointer to the copy.
|
||||
*/
|
||||
abstract fun getPointer(placement: NativePlacement): CPointer<T>
|
||||
}
|
||||
|
||||
inline fun <T : CPointed, R> CValuesRef<T>?.usePointer(block: (CPointer<T>?) -> R): R {
|
||||
val allocated: Boolean
|
||||
val pointer: CPointer<T>? = if (this is CPointer<T>?) {
|
||||
allocated = false
|
||||
this
|
||||
} else {
|
||||
allocated = true
|
||||
this!!.getPointer(nativeHeap)
|
||||
}
|
||||
|
||||
return try {
|
||||
block(pointer)
|
||||
} finally {
|
||||
if (allocated) {
|
||||
nativeHeap.free(pointer.rawValue)
|
||||
}
|
||||
}
|
||||
abstract fun getPointer(scope: AutofreeScope): CPointer<T>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +81,7 @@ abstract class CValues<T : CVariable> : CValuesRef<T>() {
|
||||
/**
|
||||
* Copies the values to [placement] and returns the pointer to the copy.
|
||||
*/
|
||||
override abstract fun getPointer(placement: NativePlacement): CPointer<T>
|
||||
override abstract fun getPointer(scope: AutofreeScope): CPointer<T>
|
||||
|
||||
// TODO: optimize
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@@ -134,7 +115,7 @@ abstract class CValues<T : CVariable> : CValuesRef<T>() {
|
||||
abstract val size: Int
|
||||
}
|
||||
|
||||
fun <T : CVariable> CValues<T>.placeTo(placement: NativePlacement) = this.getPointer(placement)
|
||||
fun <T : CVariable> CValues<T>.placeTo(scope: AutofreeScope) = this.getPointer(scope)
|
||||
|
||||
/**
|
||||
* The single immutable C value.
|
||||
@@ -163,7 +144,7 @@ class CPointer<T : CPointed> internal constructor(val rawValue: NativePtr) : CVa
|
||||
|
||||
override fun toString() = this.cPointerToString()
|
||||
|
||||
override fun getPointer(placement: NativePlacement) = this
|
||||
override fun getPointer(scope: AutofreeScope) = this
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,11 @@ open class DeferScope {
|
||||
}
|
||||
}
|
||||
|
||||
open class ArenaBase(private val parent: NativeFreeablePlacement = nativeHeap) : NativePlacement, DeferScope() {
|
||||
abstract class AutofreeScope : DeferScope(), NativePlacement {
|
||||
override abstract fun alloc(size: Long, align: Int): NativePointed
|
||||
}
|
||||
|
||||
open class ArenaBase(private val parent: NativeFreeablePlacement = nativeHeap) : AutofreeScope() {
|
||||
|
||||
private var lastChunk: NativePointed? = null
|
||||
|
||||
@@ -209,8 +213,8 @@ fun NativePlacement.allocArrayOf(vararg elements: Float): CArrayPointer<FloatVar
|
||||
fun <T : CPointed> NativePlacement.allocPointerTo() = alloc<CPointerVar<T>>()
|
||||
|
||||
fun <T : CVariable> zeroValue(size: Int, align: Int): CValue<T> = object : CValue<T>() {
|
||||
override fun getPointer(placement: NativePlacement): CPointer<T> {
|
||||
val result = placement.alloc(size, align)
|
||||
override fun getPointer(scope: AutofreeScope): CPointer<T> {
|
||||
val result = scope.alloc(size, align)
|
||||
nativeMemUtils.zeroMemory(result, size)
|
||||
return interpretCPointer(result.rawPtr)!!
|
||||
}
|
||||
@@ -232,7 +236,7 @@ fun <T : CVariable> CPointed.readValues(size: Int, align: Int): CValues<T> {
|
||||
nativeMemUtils.getByteArray(this, bytes, size)
|
||||
|
||||
return object : CValues<T>() {
|
||||
override fun getPointer(placement: NativePlacement): CPointer<T> = placement.placeBytes(bytes, align)
|
||||
override fun getPointer(scope: AutofreeScope): CPointer<T> = scope.placeBytes(bytes, align)
|
||||
override val size get() = bytes.size
|
||||
}
|
||||
}
|
||||
@@ -244,7 +248,7 @@ fun <T : CVariable> CPointed.readValue(size: Long, align: Int): CValue<T> {
|
||||
val bytes = ByteArray(size.toInt())
|
||||
nativeMemUtils.getByteArray(this, bytes, size.toInt())
|
||||
return object : CValue<T>() {
|
||||
override fun getPointer(placement: NativePlacement): CPointer<T> = placement.placeBytes(bytes, align)
|
||||
override fun getPointer(scope: AutofreeScope): CPointer<T> = scope.placeBytes(bytes, align)
|
||||
override val size get() = bytes.size
|
||||
}
|
||||
}
|
||||
@@ -255,7 +259,7 @@ inline fun <reified T : CStructVar> T.readValue(): CValue<T> = this.readValue(si
|
||||
|
||||
fun CValue<*>.write(location: NativePtr) {
|
||||
// TODO: probably CValue must be redesigned.
|
||||
val fakePlacement = object : NativePlacement {
|
||||
val fakeScope = object : AutofreeScope() {
|
||||
var used = false
|
||||
override fun alloc(size: Long, align: Int): NativePointed {
|
||||
assert(!used)
|
||||
@@ -264,8 +268,8 @@ fun CValue<*>.write(location: NativePtr) {
|
||||
}
|
||||
}
|
||||
|
||||
this.getPointer(fakePlacement)
|
||||
assert(fakePlacement.used)
|
||||
this.getPointer(fakeScope)
|
||||
assert(fakeScope.used)
|
||||
}
|
||||
|
||||
// TODO: optimize
|
||||
@@ -302,7 +306,7 @@ inline fun <reified T : CVariable> createValues(count: Int, initializer: T.(inde
|
||||
}
|
||||
|
||||
fun cValuesOf(vararg elements: Byte): CValues<ByteVar> = object : CValues<ByteVar>() {
|
||||
override fun getPointer(placement: NativePlacement) = placement.allocArrayOf(elements)
|
||||
override fun getPointer(scope: AutofreeScope) = scope.allocArrayOf(elements)
|
||||
override val size get() = 1 * elements.size
|
||||
}
|
||||
|
||||
@@ -318,7 +322,7 @@ fun cValuesOf(vararg elements: Long): CValues<LongVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun cValuesOf(vararg elements: Float): CValues<FloatVar> = object : CValues<FloatVar>() {
|
||||
override fun getPointer(placement: NativePlacement) = placement.allocArrayOf(*elements)
|
||||
override fun getPointer(scope: AutofreeScope) = scope.allocArrayOf(*elements)
|
||||
override val size get() = 4 * elements.size
|
||||
}
|
||||
|
||||
@@ -348,8 +352,8 @@ val String.cstr: CValues<ByteVar>
|
||||
return object : CValues<ByteVar>() {
|
||||
override val size get() = bytes.size + 1
|
||||
|
||||
override fun getPointer(placement: NativePlacement): CPointer<ByteVar> {
|
||||
val result = placement.allocArray<ByteVar>(bytes.size + 1)
|
||||
override fun getPointer(scope: AutofreeScope): CPointer<ByteVar> {
|
||||
val result = scope.allocArray<ByteVar>(bytes.size + 1)
|
||||
nativeMemUtils.putByteArray(bytes, result.pointed, bytes.size)
|
||||
result[bytes.size] = 0.toByte()
|
||||
return result
|
||||
@@ -363,8 +367,8 @@ val String.wcstr: CValues<ShortVar>
|
||||
return object : CValues<ShortVar>() {
|
||||
override val size get() = 2 * (chars.size + 1)
|
||||
|
||||
override fun getPointer(placement: NativePlacement): CPointer<ShortVar> {
|
||||
val result = placement.allocArray<ShortVar>(chars.size + 1)
|
||||
override fun getPointer(scope: AutofreeScope): CPointer<ShortVar> {
|
||||
val result = scope.allocArray<ShortVar>(chars.size + 1)
|
||||
nativeMemUtils.putCharArray(chars, result.pointed, chars.size)
|
||||
result[chars.size] = 0.toShort()
|
||||
return result
|
||||
|
||||
@@ -16,7 +16,7 @@ const val FFI_TYPE_KIND_POINTER: FfiTypeKind = 7
|
||||
|
||||
private tailrec fun convertArgument(
|
||||
argument: Any?, isVariadic: Boolean, location: COpaquePointer,
|
||||
additionalPlacement: NativePlacement
|
||||
additionalPlacement: AutofreeScope
|
||||
): FfiTypeKind = when (argument) {
|
||||
is CValuesRef<*>? -> {
|
||||
location.reinterpret<CPointerVar<*>>()[0] = argument?.getPointer(additionalPlacement)
|
||||
@@ -96,7 +96,7 @@ inline fun <reified T : CVariable> NativePlacement.allocFfiReturnValueBuffer(ty
|
||||
|
||||
fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind,
|
||||
fixedArguments: Array<out Any?>, variadicArguments: Array<out Any?>,
|
||||
argumentsPlacement: NativePlacement) {
|
||||
argumentsPlacement: AutofreeScope) {
|
||||
|
||||
val totalArgumentsNumber = fixedArguments.size + variadicArguments.size
|
||||
|
||||
|
||||
+8
@@ -40,6 +40,14 @@ class KotlinCodeBuilder {
|
||||
lines.add(" ".repeat(nesting) + line)
|
||||
}
|
||||
|
||||
private var memScoped = false
|
||||
fun pushMemScoped() {
|
||||
if (!memScoped) {
|
||||
memScoped = true
|
||||
pushBlock("memScoped {")
|
||||
}
|
||||
}
|
||||
|
||||
fun pushBlock(line: String, free: String = "") {
|
||||
out(line)
|
||||
freeStack.add(free)
|
||||
|
||||
+3
-3
@@ -41,9 +41,9 @@ class MappingBridgeGeneratorImpl(
|
||||
|
||||
kotlinValues.forEachIndexed { index, (type, value) ->
|
||||
if (type.unwrapTypedefs() is RecordType) {
|
||||
val tmpVarName = "kni$index"
|
||||
builder.pushBlock("$value.usePointer { $tmpVarName ->")
|
||||
bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, "$tmpVarName.rawValue"))
|
||||
builder.pushMemScoped()
|
||||
val bridgeArgument = "$value.getPointer(memScope).rawValue"
|
||||
bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, bridgeArgument))
|
||||
} else {
|
||||
val info = mirror(declarationMapper, type).info
|
||||
bridgeArguments.add(BridgeTypedKotlinValue(info.bridgedType, info.argToBridged(value)))
|
||||
|
||||
+7
-9
@@ -599,24 +599,22 @@ class StubGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
val tmpVarName = "kniTmp$index"
|
||||
|
||||
val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type)
|
||||
|
||||
val bridgeArgument = if (representCFunctionParameterAsString(parameter.type)) {
|
||||
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
||||
bodyGenerator.pushBlock("$parameterName?.cstr.usePointer { $tmpVarName ->")
|
||||
tmpVarName
|
||||
bodyGenerator.pushMemScoped()
|
||||
"$parameterName?.cstr?.getPointer(memScope)"
|
||||
} else if (representCFunctionParameterAsWString(parameter.type)) {
|
||||
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
||||
bodyGenerator.pushBlock("$parameterName?.wcstr.usePointer { $tmpVarName ->")
|
||||
tmpVarName
|
||||
bodyGenerator.pushMemScoped()
|
||||
"$parameterName?.wcstr?.getPointer(memScope)"
|
||||
} else if (representAsValuesRef != null) {
|
||||
val pointedType = mirror(representAsValuesRef).pointedType
|
||||
val parameterType = KotlinTypes.cValuesRef.typeWith(pointedType).makeNullable()
|
||||
kotlinParameters.add(parameterName to parameterType)
|
||||
bodyGenerator.pushBlock("$parameterName.usePointer { $tmpVarName ->")
|
||||
tmpVarName
|
||||
bodyGenerator.pushMemScoped()
|
||||
"$parameterName?.getPointer(memScope)"
|
||||
} else {
|
||||
val mirror = mirror(parameter.type)
|
||||
kotlinParameters.add(parameterName to mirror.argType)
|
||||
@@ -640,7 +638,7 @@ class StubGenerator(
|
||||
val returnTypeKind = getFfiTypeKind(func.returnType)
|
||||
|
||||
kotlinParameters.add("vararg variadicArguments" to KotlinTypes.any.makeNullable())
|
||||
bodyGenerator.pushBlock("memScoped {")
|
||||
bodyGenerator.pushMemScoped()
|
||||
|
||||
val resultVar = "kniResult"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user