Simplify working with values in interop
* Access primitive interop array elements and struct fields without `.value` * Simplify C*Var* interop types names
This commit is contained in:
committed by
SvyatoslavScherbina
parent
f94a47518a
commit
50c3be3fc2
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlinx.cinterop
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Byte> CPointer<ByteVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<ByteVarOf<T>>(this.rawValue + index * 1L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Byte> CPointer<ByteVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<ByteVarOf<T>>(this.rawValue + index * 1L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Byte")
|
||||
operator fun <T : ByteVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 1L)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Short> CPointer<ShortVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<ShortVarOf<T>>(this.rawValue + index * 2L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Short> CPointer<ShortVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<ShortVarOf<T>>(this.rawValue + index * 2L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Short")
|
||||
operator fun <T : ShortVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 2L)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Int> CPointer<IntVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<IntVarOf<T>>(this.rawValue + index * 4L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Int> CPointer<IntVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<IntVarOf<T>>(this.rawValue + index * 4L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Int")
|
||||
operator fun <T : IntVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 4L)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Long> CPointer<LongVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<LongVarOf<T>>(this.rawValue + index * 8L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Long> CPointer<LongVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<LongVarOf<T>>(this.rawValue + index * 8L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Long")
|
||||
operator fun <T : LongVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 8L)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Float> CPointer<FloatVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<FloatVarOf<T>>(this.rawValue + index * 4L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Float> CPointer<FloatVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<FloatVarOf<T>>(this.rawValue + index * 4L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Float")
|
||||
operator fun <T : FloatVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 4L)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Double> CPointer<DoubleVarOf<T>>.get(index: Int): T =
|
||||
interpretPointed<DoubleVarOf<T>>(this.rawValue + index * 8L).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : Double> CPointer<DoubleVarOf<T>>.set(index: Int, value: T) {
|
||||
interpretPointed<DoubleVarOf<T>>(this.rawValue + index * 8L).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$Double")
|
||||
operator fun <T : DoubleVar> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 8L)
|
||||
|
||||
/* Generated by:
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
function gen {
|
||||
echo '@Suppress("FINAL_UPPER_BOUND")'
|
||||
echo "operator fun <T : $1> CPointer<${1}VarOf<T>>.get(index: Int): T ="
|
||||
echo " interpretPointed<${1}VarOf<T>>(this.rawValue + index * ${2}L).value"
|
||||
echo
|
||||
echo '@Suppress("FINAL_UPPER_BOUND")'
|
||||
echo "operator fun <T : $1> CPointer<${1}VarOf<T>>.set(index: Int, value: T) {"
|
||||
echo " interpretPointed<${1}VarOf<T>>(this.rawValue + index * ${2}L).value = value"
|
||||
echo '}'
|
||||
echo
|
||||
echo '@Suppress("FINAL_UPPER_BOUND")'
|
||||
echo "@JvmName(\"plus\\\$$1\")"
|
||||
echo "operator fun <T : ${1}Var> CPointer<T>?.plus(index: Int): CPointer<T>? ="
|
||||
echo " interpretCPointer(this.rawValue + index * ${2}L)"
|
||||
echo
|
||||
}
|
||||
|
||||
gen Byte 1
|
||||
gen Short 2
|
||||
gen Int 4
|
||||
gen Long 8
|
||||
gen Float 4
|
||||
gen Double 8
|
||||
|
||||
*/
|
||||
@@ -174,7 +174,7 @@ typealias COpaquePointer = CPointer<out CPointed> // FIXME
|
||||
/**
|
||||
* The variable containing a [COpaquePointer].
|
||||
*/
|
||||
typealias COpaquePointerVar = CPointerVarWithValueMappedTo<COpaquePointer>
|
||||
typealias COpaquePointerVar = CPointerVarOf<COpaquePointer>
|
||||
|
||||
/**
|
||||
* The C data variable located in memory.
|
||||
@@ -238,89 +238,89 @@ abstract class CEnumVar : CPrimitiveVar()
|
||||
// these classes are not supposed to be used directly, instead the typealiases are provided.
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CInt8VarWithValueMappedTo<T : Byte>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class ByteVarOf<T : Byte>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(1)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CInt16VarWithValueMappedTo<T : Short>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class ShortVarOf<T : Short>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(2)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CInt32VarWithValueMappedTo<T : Int>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class IntVarOf<T : Int>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(4)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CInt64VarWithValueMappedTo<T : Long>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class LongVarOf<T : Long>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(8)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CFloat32VarWithValueMappedTo<T : Float>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class FloatVarOf<T : Float>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(4)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class CFloat64VarWithValueMappedTo<T : Double>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
class DoubleVarOf<T : Double>(override val rawPtr: NativePtr) : CPrimitiveVar() {
|
||||
companion object : Type(8)
|
||||
}
|
||||
|
||||
typealias CInt8Var = CInt8VarWithValueMappedTo<Byte>
|
||||
typealias CInt16Var = CInt16VarWithValueMappedTo<Short>
|
||||
typealias CInt32Var = CInt32VarWithValueMappedTo<Int>
|
||||
typealias CInt64Var = CInt64VarWithValueMappedTo<Long>
|
||||
typealias CFloat32Var = CFloat32VarWithValueMappedTo<Float>
|
||||
typealias CFloat64Var = CFloat64VarWithValueMappedTo<Double>
|
||||
typealias ByteVar = ByteVarOf<Byte>
|
||||
typealias ShortVar = ShortVarOf<Short>
|
||||
typealias IntVar = IntVarOf<Int>
|
||||
typealias LongVar = LongVarOf<Long>
|
||||
typealias FloatVar = FloatVarOf<Float>
|
||||
typealias DoubleVar = DoubleVarOf<Double>
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Byte> CInt8VarWithValueMappedTo<T>.value: T
|
||||
var <T : Byte> ByteVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getByte(this) as T
|
||||
set(value) = nativeMemUtils.putByte(this, value)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Short> CInt16VarWithValueMappedTo<T>.value: T
|
||||
var <T : Short> ShortVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getShort(this) as T
|
||||
set(value) = nativeMemUtils.putShort(this, value)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Int> CInt32VarWithValueMappedTo<T>.value: T
|
||||
var <T : Int> IntVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getInt(this) as T
|
||||
set(value) = nativeMemUtils.putInt(this, value)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Long> CInt64VarWithValueMappedTo<T>.value: T
|
||||
var <T : Long> LongVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getLong(this) as T
|
||||
set(value) = nativeMemUtils.putLong(this, value)
|
||||
|
||||
// TODO: ensure native floats have the appropriate binary representation
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Float> CFloat32VarWithValueMappedTo<T>.value: T
|
||||
var <T : Float> FloatVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getFloat(this) as T
|
||||
set(value) = nativeMemUtils.putFloat(this, value)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : Double> CFloat64VarWithValueMappedTo<T>.value: T
|
||||
var <T : Double> DoubleVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getDouble(this) as T
|
||||
set(value) = nativeMemUtils.putDouble(this, value)
|
||||
|
||||
|
||||
class CPointerVarWithValueMappedTo<T : CPointer<*>>(override val rawPtr: NativePtr) : CVariable {
|
||||
class CPointerVarOf<T : CPointer<*>>(override val rawPtr: NativePtr) : CVariable {
|
||||
companion object : CVariable.Type(pointerSize.toLong(), pointerSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* The C data variable containing the pointer to `T`.
|
||||
*/
|
||||
typealias CPointerVar<T> = CPointerVarWithValueMappedTo<CPointer<T>>
|
||||
typealias CPointerVar<T> = CPointerVarOf<CPointer<T>>
|
||||
|
||||
/**
|
||||
* The value of this variable.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline var <P : CPointer<*>> CPointerVarWithValueMappedTo<P>.value: P?
|
||||
inline var <P : CPointer<*>> CPointerVarOf<P>.value: P?
|
||||
get() = interpretCPointer<CPointed>(nativeMemUtils.getNativePtr(this)) as P?
|
||||
set(value) = nativeMemUtils.putNativePtr(this, value.rawValue)
|
||||
|
||||
@@ -329,7 +329,7 @@ inline var <P : CPointer<*>> CPointerVarWithValueMappedTo<P>.value: P?
|
||||
*
|
||||
* @param T must not be abstract
|
||||
*/
|
||||
inline var <reified T : CPointed, reified P : CPointer<T>> CPointerVarWithValueMappedTo<P>.pointed: T?
|
||||
inline var <reified T : CPointed, reified P : CPointer<T>> CPointerVarOf<P>.pointed: T?
|
||||
get() = this.value?.pointed
|
||||
set(value) {
|
||||
this.value = value?.ptr as P?
|
||||
@@ -346,6 +346,20 @@ inline operator fun <reified T : CVariable> CPointer<T>.get(index: Long): T {
|
||||
|
||||
inline operator fun <reified T : CVariable> CPointer<T>.get(index: Int): T = this.get(index.toLong())
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : CPointer<*>> CPointer<CPointerVarOf<T>>.get(index: Int): T? =
|
||||
interpretPointed<CPointerVarOf<T>>(this.rawValue + index * pointerSize.toLong()).value
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
operator fun <T : CPointer<*>> CPointer<CPointerVarOf<T>>.set(index: Int, value: T?) {
|
||||
interpretPointed<CPointerVarOf<T>>(this.rawValue + index * pointerSize.toLong()).value = value
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
@JvmName("plus\$CPointer")
|
||||
operator fun <T : CPointerVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * pointerSize.toLong())
|
||||
|
||||
typealias CArrayPointer<T> = CPointer<T>
|
||||
typealias CArrayPointerVar<T> = CPointerVar<T>
|
||||
|
||||
@@ -397,4 +411,4 @@ typealias CFunctionPointer<T> = CPointer<CFunction<T>>
|
||||
* The variable containing a [CFunctionPointer].
|
||||
* TODO: remove.
|
||||
*/
|
||||
typealias CFunctionPointerVar<T> = CPointerVarWithValueMappedTo<CFunctionPointer<T>>
|
||||
typealias CFunctionPointerVar<T> = CPointerVarOf<CFunctionPointer<T>>
|
||||
@@ -117,7 +117,7 @@ inline fun <reified T : CVariable> NativePlacement.allocArray(length: Int,
|
||||
fun <T : CPointed> NativePlacement.allocArrayOfPointersTo(elements: List<T?>): CArrayPointer<CPointerVar<T>> {
|
||||
val res = allocArray<CPointerVar<T>>(elements.size)
|
||||
elements.forEachIndexed { index, value ->
|
||||
res[index].value = value?.ptr
|
||||
res[index] = value?.ptr
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -132,7 +132,7 @@ fun <T : CPointed> NativePlacement.allocArrayOfPointersTo(vararg elements: T?) =
|
||||
* Allocates C array of given values.
|
||||
*/
|
||||
inline fun <reified T : CPointer<*>>
|
||||
NativePlacement.allocArrayOf(vararg elements: T?): CArrayPointer<CPointerVarWithValueMappedTo<T>> {
|
||||
NativePlacement.allocArrayOf(vararg elements: T?): CArrayPointer<CPointerVarOf<T>> {
|
||||
|
||||
return allocArrayOf(listOf(*elements))
|
||||
}
|
||||
@@ -141,27 +141,27 @@ inline fun <reified T : CPointer<*>>
|
||||
* Allocates C array of given values.
|
||||
*/
|
||||
inline fun <reified T : CPointer<*>>
|
||||
NativePlacement.allocArrayOf(elements: List<T?>): CArrayPointer<CPointerVarWithValueMappedTo<T>> {
|
||||
NativePlacement.allocArrayOf(elements: List<T?>): CArrayPointer<CPointerVarOf<T>> {
|
||||
|
||||
val res = allocArray<CPointerVarWithValueMappedTo<T>>(elements.size)
|
||||
val res = allocArray<CPointerVarOf<T>>(elements.size)
|
||||
elements.forEachIndexed { index, value ->
|
||||
res[index].value = value
|
||||
res[index] = value
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fun NativePlacement.allocArrayOf(elements: ByteArray): CArrayPointer<CInt8Var> {
|
||||
val result = allocArray<CInt8Var>(elements.size)
|
||||
fun NativePlacement.allocArrayOf(elements: ByteArray): CArrayPointer<ByteVar> {
|
||||
val result = allocArray<ByteVar>(elements.size)
|
||||
nativeMemUtils.putByteArray(elements, result.pointed, elements.size)
|
||||
return result
|
||||
}
|
||||
|
||||
fun NativePlacement.allocArrayOf(vararg elements: Float): CArrayPointer<CFloat32Var> {
|
||||
val res = allocArray<CFloat32Var>(elements.size)
|
||||
fun NativePlacement.allocArrayOf(vararg elements: Float): CArrayPointer<FloatVar> {
|
||||
val res = allocArray<FloatVar>(elements.size)
|
||||
var index = 0
|
||||
for (element in elements) {
|
||||
res[index++].value = element
|
||||
res[index++] = element
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -218,7 +218,7 @@ fun <T : CVariable> CValues<T>.getBytes(): ByteArray = memScoped {
|
||||
val result = ByteArray(size)
|
||||
|
||||
nativeMemUtils.getByteArray(
|
||||
source = this@getBytes.placeTo(memScope).reinterpret<CInt8Var>().pointed,
|
||||
source = this@getBytes.placeTo(memScope).reinterpret<ByteVar>().pointed,
|
||||
dest = result,
|
||||
length = result.size
|
||||
)
|
||||
@@ -246,28 +246,28 @@ inline fun <reified T : CVariable> createValues(count: Int, initializer: T.(inde
|
||||
array[0].readValues(count)
|
||||
}
|
||||
|
||||
fun cValuesOf(vararg elements: Byte): CValues<CInt8Var> = object : CValues<CInt8Var>() {
|
||||
fun cValuesOf(vararg elements: Byte): CValues<ByteVar> = object : CValues<ByteVar>() {
|
||||
override fun getPointer(placement: NativePlacement) = placement.allocArrayOf(elements)
|
||||
override val size get() = 1 * elements.size
|
||||
}
|
||||
|
||||
// TODO: optimize other [cValuesOf] methods:
|
||||
|
||||
fun cValuesOf(vararg elements: Short): CValues<CInt16Var> =
|
||||
fun cValuesOf(vararg elements: Short): CValues<ShortVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun cValuesOf(vararg elements: Int): CValues<CInt32Var> =
|
||||
fun cValuesOf(vararg elements: Int): CValues<IntVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun cValuesOf(vararg elements: Long): CValues<CInt64Var> =
|
||||
fun cValuesOf(vararg elements: Long): CValues<LongVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun cValuesOf(vararg elements: Float): CValues<CFloat32Var> = object : CValues<CFloat32Var>() {
|
||||
fun cValuesOf(vararg elements: Float): CValues<FloatVar> = object : CValues<FloatVar>() {
|
||||
override fun getPointer(placement: NativePlacement) = placement.allocArrayOf(*elements)
|
||||
override val size get() = 4 * elements.size
|
||||
}
|
||||
|
||||
fun cValuesOf(vararg elements: Double): CValues<CFloat64Var> =
|
||||
fun cValuesOf(vararg elements: Double): CValues<DoubleVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun <T : CPointed> cValuesOf(vararg elements: CPointer<T>?): CValues<CPointerVar<T>> =
|
||||
@@ -288,17 +288,17 @@ fun <T : CPointed> List<CPointer<T>?>.toCValues() = this.toTypedArray().toCValue
|
||||
*
|
||||
* @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String].
|
||||
*/
|
||||
val String.cstr: CValues<CInt8Var>
|
||||
val String.cstr: CValues<ByteVar>
|
||||
get() {
|
||||
val bytes = encodeToUtf8(this)
|
||||
|
||||
return object : CValues<CInt8Var>() {
|
||||
return object : CValues<ByteVar>() {
|
||||
override val size get() = bytes.size + 1
|
||||
|
||||
override fun getPointer(placement: NativePlacement): CPointer<CInt8Var> {
|
||||
val result = placement.allocArray<CInt8Var>(bytes.size + 1)
|
||||
override fun getPointer(placement: NativePlacement): CPointer<ByteVar> {
|
||||
val result = placement.allocArray<ByteVar>(bytes.size + 1)
|
||||
nativeMemUtils.putByteArray(bytes, result.pointed, bytes.size)
|
||||
result[bytes.size].value = 0.toByte()
|
||||
result[bytes.size] = 0.toByte()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -309,11 +309,11 @@ val String.cstr: CValues<CInt8Var>
|
||||
*
|
||||
* @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string.
|
||||
*/
|
||||
fun CPointer<CInt8Var>.toKString(): String {
|
||||
fun CPointer<ByteVar>.toKString(): String {
|
||||
val nativeBytes = this
|
||||
|
||||
var length = 0
|
||||
while (nativeBytes[length].value != 0.toByte()) {
|
||||
while (nativeBytes[length] != 0.toByte()) {
|
||||
++length
|
||||
}
|
||||
|
||||
|
||||
@@ -32,25 +32,25 @@ object nativeMemUtils {
|
||||
|
||||
// TODO: optimize
|
||||
fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) {
|
||||
val sourceArray = source.reinterpret<CInt8Var>().ptr
|
||||
val sourceArray = source.reinterpret<ByteVar>().ptr
|
||||
for (index in 0 .. length - 1) {
|
||||
dest[index] = sourceArray[index].value
|
||||
dest[index] = sourceArray[index]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: optimize
|
||||
fun putByteArray(source: ByteArray, dest: NativePointed, length: Int) {
|
||||
val destArray = dest.reinterpret<CInt8Var>().ptr
|
||||
val destArray = dest.reinterpret<ByteVar>().ptr
|
||||
for (index in 0 .. length - 1) {
|
||||
destArray[index].value = source[index]
|
||||
destArray[index] = source[index]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: optimize
|
||||
fun zeroMemory(dest: NativePointed, length: Int): Unit {
|
||||
val destArray = dest.reinterpret<CInt8Var>().ptr
|
||||
val destArray = dest.reinterpret<ByteVar>().ptr
|
||||
for (index in 0 .. length - 1) {
|
||||
destArray[index].value = 0
|
||||
destArray[index] = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,3 +28,7 @@ external fun <R : Number> Number.signExtend(): R
|
||||
|
||||
@Intrinsic
|
||||
external fun <R : Number> Number.narrow(): R
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
internal annotation class JvmName(val name: String)
|
||||
@@ -15,52 +15,52 @@ const val FFI_TYPE_KIND_DOUBLE: FfiTypeKind = 6
|
||||
const val FFI_TYPE_KIND_POINTER: FfiTypeKind = 7
|
||||
|
||||
private tailrec fun convertArgument(
|
||||
argument: Any?, isVariadic: Boolean, location: NativePointed,
|
||||
argument: Any?, isVariadic: Boolean, location: COpaquePointer,
|
||||
additionalPlacement: NativePlacement
|
||||
): FfiTypeKind = when (argument) {
|
||||
is CValuesRef<*>? -> {
|
||||
location.reinterpret<CPointerVar<*>>().value = argument?.getPointer(additionalPlacement)
|
||||
location.reinterpret<CPointerVar<*>>()[0] = argument?.getPointer(additionalPlacement)
|
||||
FFI_TYPE_KIND_POINTER
|
||||
}
|
||||
|
||||
is String -> {
|
||||
location.reinterpret<CPointerVar<*>>().value = argument.cstr.getPointer(additionalPlacement)
|
||||
location.reinterpret<CPointerVar<*>>()[0] = argument.cstr.getPointer(additionalPlacement)
|
||||
FFI_TYPE_KIND_POINTER
|
||||
}
|
||||
|
||||
is Int -> {
|
||||
location.reinterpret<CInt32Var>().value = argument
|
||||
location.reinterpret<IntVar>()[0] = argument
|
||||
FFI_TYPE_KIND_SINT32
|
||||
}
|
||||
|
||||
is Long -> {
|
||||
location.reinterpret<CInt64Var>().value = argument
|
||||
location.reinterpret<LongVar>()[0] = argument
|
||||
FFI_TYPE_KIND_SINT64
|
||||
}
|
||||
|
||||
is Byte -> if (isVariadic) {
|
||||
convertArgument(argument.toInt(), isVariadic, location, additionalPlacement)
|
||||
} else {
|
||||
location.reinterpret<CInt8Var>().value = argument
|
||||
location.reinterpret<ByteVar>()[0] = argument
|
||||
FFI_TYPE_KIND_SINT8
|
||||
}
|
||||
|
||||
is Short -> if (isVariadic) {
|
||||
convertArgument(argument.toInt(), isVariadic, location, additionalPlacement)
|
||||
} else {
|
||||
location.reinterpret<CInt16Var>().value = argument
|
||||
location.reinterpret<ShortVar>()[0] = argument
|
||||
FFI_TYPE_KIND_SINT16
|
||||
}
|
||||
|
||||
is Double -> {
|
||||
location.reinterpret<CFloat64Var>().value = argument
|
||||
location.reinterpret<DoubleVar>()[0] = argument
|
||||
FFI_TYPE_KIND_DOUBLE
|
||||
}
|
||||
|
||||
is Float -> if (isVariadic) {
|
||||
convertArgument(argument.toDouble(), isVariadic, location, additionalPlacement)
|
||||
} else {
|
||||
location.reinterpret<CFloat32Var>().value = argument
|
||||
location.reinterpret<FloatVar>()[0] = argument
|
||||
FFI_TYPE_KIND_FLOAT
|
||||
}
|
||||
|
||||
@@ -76,19 +76,19 @@ fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKin
|
||||
val totalArgumentsNumber = fixedArguments.size + variadicArguments.size
|
||||
|
||||
// All supported arguments take at most 8 bytes each:
|
||||
val argumentsStorage = argumentsPlacement.allocArray<CInt64Var>(totalArgumentsNumber)
|
||||
val argumentsStorage = argumentsPlacement.allocArray<LongVar>(totalArgumentsNumber)
|
||||
val arguments = argumentsPlacement.allocArray<CPointerVar<*>>(totalArgumentsNumber)
|
||||
val types = argumentsPlacement.allocArray<CPointerVar<*>>(totalArgumentsNumber)
|
||||
|
||||
var index = 0
|
||||
|
||||
inline fun addArgument(argument: Any?, isVariadic: Boolean) {
|
||||
val storage = argumentsStorage[index]
|
||||
val storage = (argumentsStorage + index)!!
|
||||
val typeKind = convertArgument(argument, isVariadic = isVariadic,
|
||||
location = storage, additionalPlacement = argumentsPlacement)
|
||||
|
||||
types[index].value = interpretCPointer<COpaque>(nativeNullPtr + typeKind.toLong())
|
||||
arguments[index].value = storage.ptr
|
||||
types[index] = interpretCPointer<COpaque>(nativeNullPtr + typeKind.toLong())
|
||||
arguments[index] = storage
|
||||
|
||||
++index
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user