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
|
return !hasChildren
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun List<String>.toNativeStringArray(placement: NativePlacement): CArrayPointer<CPointerVar<ByteVar>> {
|
internal fun List<String>.toNativeStringArray(scope: AutofreeScope): CArrayPointer<CPointerVar<ByteVar>> {
|
||||||
return placement.allocArray(this.size) { index ->
|
return scope.allocArray(this.size) { index ->
|
||||||
this.value = this@toNativeStringArray[index].cstr.getPointer(placement)
|
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.
|
* If this reference is [CPointer], returns this pointer.
|
||||||
* Otherwise copies the referenced values to [placement] and returns the pointer to the copy.
|
* Otherwise copies the referenced values to [placement] and returns the pointer to the copy.
|
||||||
*/
|
*/
|
||||||
abstract fun getPointer(placement: NativePlacement): CPointer<T>
|
abstract fun getPointer(scope: AutofreeScope): 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,7 +81,7 @@ abstract class CValues<T : CVariable> : CValuesRef<T>() {
|
|||||||
/**
|
/**
|
||||||
* Copies the values to [placement] and returns the pointer to the copy.
|
* 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
|
// TODO: optimize
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@@ -134,7 +115,7 @@ abstract class CValues<T : CVariable> : CValuesRef<T>() {
|
|||||||
abstract val size: Int
|
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.
|
* 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 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
|
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 : CPointed> NativePlacement.allocPointerTo() = alloc<CPointerVar<T>>()
|
||||||
|
|
||||||
fun <T : CVariable> zeroValue(size: Int, align: Int): CValue<T> = object : CValue<T>() {
|
fun <T : CVariable> zeroValue(size: Int, align: Int): CValue<T> = object : CValue<T>() {
|
||||||
override fun getPointer(placement: NativePlacement): CPointer<T> {
|
override fun getPointer(scope: AutofreeScope): CPointer<T> {
|
||||||
val result = placement.alloc(size, align)
|
val result = scope.alloc(size, align)
|
||||||
nativeMemUtils.zeroMemory(result, size)
|
nativeMemUtils.zeroMemory(result, size)
|
||||||
return interpretCPointer(result.rawPtr)!!
|
return interpretCPointer(result.rawPtr)!!
|
||||||
}
|
}
|
||||||
@@ -232,7 +236,7 @@ fun <T : CVariable> CPointed.readValues(size: Int, align: Int): CValues<T> {
|
|||||||
nativeMemUtils.getByteArray(this, bytes, size)
|
nativeMemUtils.getByteArray(this, bytes, size)
|
||||||
|
|
||||||
return object : CValues<T>() {
|
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
|
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())
|
val bytes = ByteArray(size.toInt())
|
||||||
nativeMemUtils.getByteArray(this, bytes, size.toInt())
|
nativeMemUtils.getByteArray(this, bytes, size.toInt())
|
||||||
return object : CValue<T>() {
|
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
|
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) {
|
fun CValue<*>.write(location: NativePtr) {
|
||||||
// TODO: probably CValue must be redesigned.
|
// TODO: probably CValue must be redesigned.
|
||||||
val fakePlacement = object : NativePlacement {
|
val fakeScope = object : AutofreeScope() {
|
||||||
var used = false
|
var used = false
|
||||||
override fun alloc(size: Long, align: Int): NativePointed {
|
override fun alloc(size: Long, align: Int): NativePointed {
|
||||||
assert(!used)
|
assert(!used)
|
||||||
@@ -264,8 +268,8 @@ fun CValue<*>.write(location: NativePtr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getPointer(fakePlacement)
|
this.getPointer(fakeScope)
|
||||||
assert(fakePlacement.used)
|
assert(fakeScope.used)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: optimize
|
// 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>() {
|
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
|
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] }
|
createValues(elements.size) { index -> this.value = elements[index] }
|
||||||
|
|
||||||
fun cValuesOf(vararg elements: Float): CValues<FloatVar> = object : CValues<FloatVar>() {
|
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
|
override val size get() = 4 * elements.size
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,8 +352,8 @@ val String.cstr: CValues<ByteVar>
|
|||||||
return object : CValues<ByteVar>() {
|
return object : CValues<ByteVar>() {
|
||||||
override val size get() = bytes.size + 1
|
override val size get() = bytes.size + 1
|
||||||
|
|
||||||
override fun getPointer(placement: NativePlacement): CPointer<ByteVar> {
|
override fun getPointer(scope: AutofreeScope): CPointer<ByteVar> {
|
||||||
val result = placement.allocArray<ByteVar>(bytes.size + 1)
|
val result = scope.allocArray<ByteVar>(bytes.size + 1)
|
||||||
nativeMemUtils.putByteArray(bytes, result.pointed, bytes.size)
|
nativeMemUtils.putByteArray(bytes, result.pointed, bytes.size)
|
||||||
result[bytes.size] = 0.toByte()
|
result[bytes.size] = 0.toByte()
|
||||||
return result
|
return result
|
||||||
@@ -363,8 +367,8 @@ val String.wcstr: CValues<ShortVar>
|
|||||||
return object : CValues<ShortVar>() {
|
return object : CValues<ShortVar>() {
|
||||||
override val size get() = 2 * (chars.size + 1)
|
override val size get() = 2 * (chars.size + 1)
|
||||||
|
|
||||||
override fun getPointer(placement: NativePlacement): CPointer<ShortVar> {
|
override fun getPointer(scope: AutofreeScope): CPointer<ShortVar> {
|
||||||
val result = placement.allocArray<ShortVar>(chars.size + 1)
|
val result = scope.allocArray<ShortVar>(chars.size + 1)
|
||||||
nativeMemUtils.putCharArray(chars, result.pointed, chars.size)
|
nativeMemUtils.putCharArray(chars, result.pointed, chars.size)
|
||||||
result[chars.size] = 0.toShort()
|
result[chars.size] = 0.toShort()
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const val FFI_TYPE_KIND_POINTER: FfiTypeKind = 7
|
|||||||
|
|
||||||
private tailrec fun convertArgument(
|
private tailrec fun convertArgument(
|
||||||
argument: Any?, isVariadic: Boolean, location: COpaquePointer,
|
argument: Any?, isVariadic: Boolean, location: COpaquePointer,
|
||||||
additionalPlacement: NativePlacement
|
additionalPlacement: AutofreeScope
|
||||||
): FfiTypeKind = when (argument) {
|
): FfiTypeKind = when (argument) {
|
||||||
is CValuesRef<*>? -> {
|
is CValuesRef<*>? -> {
|
||||||
location.reinterpret<CPointerVar<*>>()[0] = argument?.getPointer(additionalPlacement)
|
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,
|
fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind,
|
||||||
fixedArguments: Array<out Any?>, variadicArguments: Array<out Any?>,
|
fixedArguments: Array<out Any?>, variadicArguments: Array<out Any?>,
|
||||||
argumentsPlacement: NativePlacement) {
|
argumentsPlacement: AutofreeScope) {
|
||||||
|
|
||||||
val totalArgumentsNumber = fixedArguments.size + variadicArguments.size
|
val totalArgumentsNumber = fixedArguments.size + variadicArguments.size
|
||||||
|
|
||||||
|
|||||||
+8
@@ -40,6 +40,14 @@ class KotlinCodeBuilder {
|
|||||||
lines.add(" ".repeat(nesting) + line)
|
lines.add(" ".repeat(nesting) + line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var memScoped = false
|
||||||
|
fun pushMemScoped() {
|
||||||
|
if (!memScoped) {
|
||||||
|
memScoped = true
|
||||||
|
pushBlock("memScoped {")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun pushBlock(line: String, free: String = "") {
|
fun pushBlock(line: String, free: String = "") {
|
||||||
out(line)
|
out(line)
|
||||||
freeStack.add(free)
|
freeStack.add(free)
|
||||||
|
|||||||
+3
-3
@@ -41,9 +41,9 @@ class MappingBridgeGeneratorImpl(
|
|||||||
|
|
||||||
kotlinValues.forEachIndexed { index, (type, value) ->
|
kotlinValues.forEachIndexed { index, (type, value) ->
|
||||||
if (type.unwrapTypedefs() is RecordType) {
|
if (type.unwrapTypedefs() is RecordType) {
|
||||||
val tmpVarName = "kni$index"
|
builder.pushMemScoped()
|
||||||
builder.pushBlock("$value.usePointer { $tmpVarName ->")
|
val bridgeArgument = "$value.getPointer(memScope).rawValue"
|
||||||
bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, "$tmpVarName.rawValue"))
|
bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, bridgeArgument))
|
||||||
} else {
|
} else {
|
||||||
val info = mirror(declarationMapper, type).info
|
val info = mirror(declarationMapper, type).info
|
||||||
bridgeArguments.add(BridgeTypedKotlinValue(info.bridgedType, info.argToBridged(value)))
|
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 representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type)
|
||||||
|
|
||||||
val bridgeArgument = if (representCFunctionParameterAsString(parameter.type)) {
|
val bridgeArgument = if (representCFunctionParameterAsString(parameter.type)) {
|
||||||
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
||||||
bodyGenerator.pushBlock("$parameterName?.cstr.usePointer { $tmpVarName ->")
|
bodyGenerator.pushMemScoped()
|
||||||
tmpVarName
|
"$parameterName?.cstr?.getPointer(memScope)"
|
||||||
} else if (representCFunctionParameterAsWString(parameter.type)) {
|
} else if (representCFunctionParameterAsWString(parameter.type)) {
|
||||||
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
|
||||||
bodyGenerator.pushBlock("$parameterName?.wcstr.usePointer { $tmpVarName ->")
|
bodyGenerator.pushMemScoped()
|
||||||
tmpVarName
|
"$parameterName?.wcstr?.getPointer(memScope)"
|
||||||
} else if (representAsValuesRef != null) {
|
} else if (representAsValuesRef != null) {
|
||||||
val pointedType = mirror(representAsValuesRef).pointedType
|
val pointedType = mirror(representAsValuesRef).pointedType
|
||||||
val parameterType = KotlinTypes.cValuesRef.typeWith(pointedType).makeNullable()
|
val parameterType = KotlinTypes.cValuesRef.typeWith(pointedType).makeNullable()
|
||||||
kotlinParameters.add(parameterName to parameterType)
|
kotlinParameters.add(parameterName to parameterType)
|
||||||
bodyGenerator.pushBlock("$parameterName.usePointer { $tmpVarName ->")
|
bodyGenerator.pushMemScoped()
|
||||||
tmpVarName
|
"$parameterName?.getPointer(memScope)"
|
||||||
} else {
|
} else {
|
||||||
val mirror = mirror(parameter.type)
|
val mirror = mirror(parameter.type)
|
||||||
kotlinParameters.add(parameterName to mirror.argType)
|
kotlinParameters.add(parameterName to mirror.argType)
|
||||||
@@ -640,7 +638,7 @@ class StubGenerator(
|
|||||||
val returnTypeKind = getFfiTypeKind(func.returnType)
|
val returnTypeKind = getFfiTypeKind(func.returnType)
|
||||||
|
|
||||||
kotlinParameters.add("vararg variadicArguments" to KotlinTypes.any.makeNullable())
|
kotlinParameters.add("vararg variadicArguments" to KotlinTypes.any.makeNullable())
|
||||||
bodyGenerator.pushBlock("memScoped {")
|
bodyGenerator.pushMemScoped()
|
||||||
|
|
||||||
val resultVar = "kniResult"
|
val resultVar = "kniResult"
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class CPointerBox(val value: CPointer<CPointed>) : CValuesRef<CPointed>() {
|
|||||||
|
|
||||||
override fun toString() = value.toString()
|
override fun toString() = value.toString()
|
||||||
|
|
||||||
override fun getPointer(placement: NativePlacement) = value.getPointer(placement)
|
override fun getPointer(scope: AutofreeScope) = value.getPointer(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun boxCPointer(value: CPointer<CPointed>?) = if (value != null) CPointerBox(value) else null
|
fun boxCPointer(value: CPointer<CPointed>?) = if (value != null) CPointerBox(value) else null
|
||||||
|
|||||||
Reference in New Issue
Block a user