Use unsigned types in interop (#1913)
This commit is contained in:
committed by
GitHub
parent
29cddb46bf
commit
8f1b94f38b
+11
-15
@@ -468,28 +468,24 @@ Sometimes the C libraries have function parameters or struct fields of
|
||||
platform-dependent type, e.g. `long` or `size_t`. Kotlin itself doesn't provide
|
||||
neither implicit integer casts nor C-style integer casts (e.g.
|
||||
`(size_t) intValue`), so to make writing portable code in such cases easier,
|
||||
the following methods are provided:
|
||||
`convert` method is provided:
|
||||
|
||||
* `fun ${type1}.signExtend<${type2}>(): ${type2}`
|
||||
* `fun ${type1}.narrow<${type2}>(): ${type2}`
|
||||
```
|
||||
fun ${type1}.convert<${type2}>(): ${type2}
|
||||
```
|
||||
|
||||
where each of `type1` and `type2` must be an integral type.
|
||||
where each of `type1` and `type2` must be an integral type, either signed or unsigned.
|
||||
|
||||
The `signExtend` converts the integer value to more wide, i.e. the result must
|
||||
have the same or greater size.
|
||||
The `narrow` converts the integer value to smaller one (possibly changing the
|
||||
value due to loosing significant bits), so the result must have the same or
|
||||
less size.
|
||||
`.convert<${type}>` has the same semantics as one of the
|
||||
`.toByte`, `.toShort`, `.toInt`, `.toLong`,
|
||||
`.toUByte`, `.toUShort`, `.toUInt` or `.toULong`
|
||||
methods, depending on `type`.
|
||||
|
||||
Any allowed `.signExtend<${type}>` or `.narrow<${type}>` have the same
|
||||
semantics as one of the `.toByte`, `.toShort`, `.toInt` or `.toLong` methods,
|
||||
depending on `type`.
|
||||
|
||||
The example of using `signExtend`:
|
||||
The example of using `convert`:
|
||||
|
||||
```
|
||||
fun zeroMemory(buffer: COpaquePointer, size: Int) {
|
||||
memset(buffer, 0, size.signExtend<size_t>())
|
||||
memset(buffer, 0, size.convert<size_t>())
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -72,6 +72,12 @@ dependencies {
|
||||
|
||||
sourceSets.main.kotlin.srcDirs += "src/jvm/kotlin"
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = ['-Xuse-experimental=kotlin.ExperimentalUnsignedTypes']
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task nativelibs(type: Copy) {
|
||||
dependsOn 'callbacksSharedLibrary'
|
||||
|
||||
@@ -121,7 +121,7 @@ private fun getEnumCType(classifier: KClass<*>): CEnumType? {
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return CEnumType(rawValueCType as CType<Number>)
|
||||
return CEnumType(rawValueCType as CType<Any>)
|
||||
}
|
||||
|
||||
private fun getArgOrRetValCType(type: KType): CType<*> {
|
||||
@@ -346,7 +346,7 @@ private class Struct(val size: Long, val align: Int, elementTypes: List<CType<*>
|
||||
override fun write(location: NativePtr, value: CValue<*>) = value.write(location)
|
||||
}
|
||||
|
||||
private class CEnumType(private val rawValueCType: CType<Number>) : CType<CEnum>(rawValueCType.ffiType) {
|
||||
private class CEnumType(private val rawValueCType: CType<Any>) : CType<CEnum>(rawValueCType.ffiType) {
|
||||
|
||||
override fun read(location: NativePtr): CEnum {
|
||||
TODO("enum-typed callback parameters")
|
||||
|
||||
@@ -26,16 +26,20 @@ inline operator fun <T : ByteVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<
|
||||
inline operator fun <T : ByteVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Byte")
|
||||
inline operator fun <T : Byte> CPointer<ByteVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Byte")
|
||||
inline operator fun <T : Byte> CPointer<ByteVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Byte")
|
||||
inline operator fun <T : Byte> CPointer<ByteVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Byte")
|
||||
inline operator fun <T : Byte> CPointer<ByteVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
@@ -48,16 +52,20 @@ inline operator fun <T : ShortVarOf<*>> CPointer<T>?.plus(index: Long): CPointer
|
||||
inline operator fun <T : ShortVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Short")
|
||||
inline operator fun <T : Short> CPointer<ShortVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Short")
|
||||
inline operator fun <T : Short> CPointer<ShortVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Short")
|
||||
inline operator fun <T : Short> CPointer<ShortVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Short")
|
||||
inline operator fun <T : Short> CPointer<ShortVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
@@ -70,16 +78,20 @@ inline operator fun <T : IntVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T
|
||||
inline operator fun <T : IntVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Int")
|
||||
inline operator fun <T : Int> CPointer<IntVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Int")
|
||||
inline operator fun <T : Int> CPointer<IntVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Int")
|
||||
inline operator fun <T : Int> CPointer<IntVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Int")
|
||||
inline operator fun <T : Int> CPointer<IntVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
@@ -92,20 +104,128 @@ inline operator fun <T : LongVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<
|
||||
inline operator fun <T : LongVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Long")
|
||||
inline operator fun <T : Long> CPointer<LongVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Long")
|
||||
inline operator fun <T : Long> CPointer<LongVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Long")
|
||||
inline operator fun <T : Long> CPointer<LongVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Long")
|
||||
inline operator fun <T : Long> CPointer<LongVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("plus\$UByte")
|
||||
inline operator fun <T : UByteVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 1)
|
||||
|
||||
@JvmName("plus\$UByte")
|
||||
inline operator fun <T : UByteVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$UByte")
|
||||
inline operator fun <T : UByte> CPointer<UByteVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UByte")
|
||||
inline operator fun <T : UByte> CPointer<UByteVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$UByte")
|
||||
inline operator fun <T : UByte> CPointer<UByteVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UByte")
|
||||
inline operator fun <T : UByte> CPointer<UByteVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("plus\$UShort")
|
||||
inline operator fun <T : UShortVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 2)
|
||||
|
||||
@JvmName("plus\$UShort")
|
||||
inline operator fun <T : UShortVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$UShort")
|
||||
inline operator fun <T : UShort> CPointer<UShortVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UShort")
|
||||
inline operator fun <T : UShort> CPointer<UShortVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$UShort")
|
||||
inline operator fun <T : UShort> CPointer<UShortVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UShort")
|
||||
inline operator fun <T : UShort> CPointer<UShortVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("plus\$UInt")
|
||||
inline operator fun <T : UIntVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 4)
|
||||
|
||||
@JvmName("plus\$UInt")
|
||||
inline operator fun <T : UIntVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$UInt")
|
||||
inline operator fun <T : UInt> CPointer<UIntVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UInt")
|
||||
inline operator fun <T : UInt> CPointer<UIntVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$UInt")
|
||||
inline operator fun <T : UInt> CPointer<UIntVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$UInt")
|
||||
inline operator fun <T : UInt> CPointer<UIntVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("plus\$ULong")
|
||||
inline operator fun <T : ULongVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 8)
|
||||
|
||||
@JvmName("plus\$ULong")
|
||||
inline operator fun <T : ULongVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$ULong")
|
||||
inline operator fun <T : ULong> CPointer<ULongVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$ULong")
|
||||
inline operator fun <T : ULong> CPointer<ULongVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$ULong")
|
||||
inline operator fun <T : ULong> CPointer<ULongVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$ULong")
|
||||
inline operator fun <T : ULong> CPointer<ULongVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("plus\$Float")
|
||||
inline operator fun <T : FloatVarOf<*>> CPointer<T>?.plus(index: Long): CPointer<T>? =
|
||||
interpretCPointer(this.rawValue + index * 4)
|
||||
@@ -114,16 +234,20 @@ inline operator fun <T : FloatVarOf<*>> CPointer<T>?.plus(index: Long): CPointer
|
||||
inline operator fun <T : FloatVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Float")
|
||||
inline operator fun <T : Float> CPointer<FloatVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Float")
|
||||
inline operator fun <T : Float> CPointer<FloatVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Float")
|
||||
inline operator fun <T : Float> CPointer<FloatVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Float")
|
||||
inline operator fun <T : Float> CPointer<FloatVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
@@ -136,16 +260,20 @@ inline operator fun <T : DoubleVarOf<*>> CPointer<T>?.plus(index: Long): CPointe
|
||||
inline operator fun <T : DoubleVarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? =
|
||||
this + index.toLong()
|
||||
|
||||
@JvmName("get\$Double")
|
||||
inline operator fun <T : Double> CPointer<DoubleVarOf<T>>.get(index: Int): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Double")
|
||||
inline operator fun <T : Double> CPointer<DoubleVarOf<T>>.set(index: Int, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
|
||||
@JvmName("get\$Double")
|
||||
inline operator fun <T : Double> CPointer<DoubleVarOf<T>>.get(index: Long): T =
|
||||
(this + index)!!.pointed.value
|
||||
|
||||
@JvmName("set\$Double")
|
||||
inline operator fun <T : Double> CPointer<DoubleVarOf<T>>.set(index: Long, value: T) {
|
||||
(this + index)!!.pointed.value = value
|
||||
}
|
||||
@@ -163,16 +291,20 @@ echo "@JvmName(\"plus\\\$$1\")"
|
||||
echo "inline operator fun <T : ${1}VarOf<*>> CPointer<T>?.plus(index: Int): CPointer<T>? ="
|
||||
echo " this + index.toLong()"
|
||||
echo
|
||||
echo "@JvmName(\"get\\\$$1\")"
|
||||
echo "inline operator fun <T : $1> CPointer<${1}VarOf<T>>.get(index: Int): T ="
|
||||
echo " (this + index)!!.pointed.value"
|
||||
echo
|
||||
echo "@JvmName(\"set\\\$$1\")"
|
||||
echo "inline operator fun <T : $1> CPointer<${1}VarOf<T>>.set(index: Int, value: T) {"
|
||||
echo " (this + index)!!.pointed.value = value"
|
||||
echo '}'
|
||||
echo
|
||||
echo "@JvmName(\"get\\\$$1\")"
|
||||
echo "inline operator fun <T : $1> CPointer<${1}VarOf<T>>.get(index: Long): T ="
|
||||
echo " (this + index)!!.pointed.value"
|
||||
echo
|
||||
echo "@JvmName(\"set\\\$$1\")"
|
||||
echo "inline operator fun <T : $1> CPointer<${1}VarOf<T>>.set(index: Long, value: T) {"
|
||||
echo " (this + index)!!.pointed.value = value"
|
||||
echo '}'
|
||||
@@ -183,6 +315,10 @@ gen Byte 1
|
||||
gen Short 2
|
||||
gen Int 4
|
||||
gen Long 8
|
||||
gen UByte 1
|
||||
gen UShort 2
|
||||
gen UInt 4
|
||||
gen ULong 8
|
||||
gen Float 4
|
||||
gen Double 8
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ sealed class CPrimitiveVar(rawPtr: NativePtr) : CVariable(rawPtr) {
|
||||
}
|
||||
|
||||
interface CEnum {
|
||||
val value: Number
|
||||
val value: Any
|
||||
}
|
||||
abstract class CEnumVar(rawPtr: NativePtr) : CPrimitiveVar(rawPtr)
|
||||
|
||||
@@ -278,6 +278,26 @@ class LongVarOf<T : Long>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(8)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class UByteVarOf<T : UByte>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(1)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class UShortVarOf<T : UShort>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(2)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class UIntVarOf<T : UInt>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(4)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class ULongVarOf<T : ULong>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(8)
|
||||
}
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND")
|
||||
class FloatVarOf<T : Float>(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) {
|
||||
companion object : Type(4)
|
||||
@@ -293,6 +313,10 @@ typealias ByteVar = ByteVarOf<Byte>
|
||||
typealias ShortVar = ShortVarOf<Short>
|
||||
typealias IntVar = IntVarOf<Int>
|
||||
typealias LongVar = LongVarOf<Long>
|
||||
typealias UByteVar = UByteVarOf<UByte>
|
||||
typealias UShortVar = UShortVarOf<UShort>
|
||||
typealias UIntVar = UIntVarOf<UInt>
|
||||
typealias ULongVar = ULongVarOf<ULong>
|
||||
typealias FloatVar = FloatVarOf<Float>
|
||||
typealias DoubleVar = DoubleVarOf<Double>
|
||||
|
||||
@@ -330,6 +354,26 @@ var <T : Long> LongVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getLong(this) as T
|
||||
set(value) = nativeMemUtils.putLong(this, value)
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : UByte> UByteVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getByte(this).toUByte() as T
|
||||
set(value) = nativeMemUtils.putByte(this, value.toByte())
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : UShort> UShortVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getShort(this).toUShort() as T
|
||||
set(value) = nativeMemUtils.putShort(this, value.toShort())
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : UInt> UIntVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getInt(this).toUInt() as T
|
||||
set(value) = nativeMemUtils.putInt(this, value.toInt())
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
var <T : ULong> ULongVarOf<T>.value: T
|
||||
get() = nativeMemUtils.getLong(this).toULong() as T
|
||||
set(value) = nativeMemUtils.putLong(this, value.toLong())
|
||||
|
||||
// TODO: ensure native floats have the appropriate binary representation
|
||||
|
||||
@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST")
|
||||
|
||||
@@ -321,6 +321,22 @@ fun cValuesOf(vararg elements: Int): CValues<IntVar> =
|
||||
fun cValuesOf(vararg elements: Long): CValues<LongVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
@JvmName("cValuesOfUnsigned")
|
||||
fun cValuesOf(vararg elements: UByte): CValues<UByteVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
@JvmName("cValuesOfUnsigned")
|
||||
fun cValuesOf(vararg elements: UShort): CValues<UShortVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
@JvmName("cValuesOfUnsigned")
|
||||
fun cValuesOf(vararg elements: UInt): CValues<UIntVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
@JvmName("cValuesOfUnsigned")
|
||||
fun cValuesOf(vararg elements: ULong): CValues<ULongVar> =
|
||||
createValues(elements.size) { index -> this.value = elements[index] }
|
||||
|
||||
fun cValuesOf(vararg elements: Float): CValues<FloatVar> = object : CValues<FloatVar>() {
|
||||
override fun getPointer(scope: AutofreeScope) = scope.allocArrayOf(*elements)
|
||||
override val size get() = 4 * elements.size
|
||||
|
||||
@@ -102,6 +102,34 @@ private fun invokeImplLongRet(ptr: COpaquePointer, vararg args: Any?): Long = me
|
||||
resultBuffer.value
|
||||
}
|
||||
|
||||
@ExportForCompiler
|
||||
private fun invokeImplUByteRet(ptr: COpaquePointer, vararg args: Any?): UByte = memScoped {
|
||||
val resultBuffer = allocFfiReturnValueBuffer<UByteVar>(UByteVar)
|
||||
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_UINT8, args, null, memScope)
|
||||
resultBuffer.value
|
||||
}
|
||||
|
||||
@ExportForCompiler
|
||||
private fun invokeImplUShortRet(ptr: COpaquePointer, vararg args: Any?): UShort = memScoped {
|
||||
val resultBuffer = allocFfiReturnValueBuffer<UShortVar>(UShortVar)
|
||||
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_UINT16, args, null, memScope)
|
||||
resultBuffer.value
|
||||
}
|
||||
|
||||
@ExportForCompiler
|
||||
private fun invokeImplUIntRet(ptr: COpaquePointer, vararg args: Any?): UInt = memScoped {
|
||||
val resultBuffer = allocFfiReturnValueBuffer<UIntVar>(UIntVar)
|
||||
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_UINT32, args, null, memScope)
|
||||
resultBuffer.value
|
||||
}
|
||||
|
||||
@ExportForCompiler
|
||||
private fun invokeImplULongRet(ptr: COpaquePointer, vararg args: Any?): ULong = memScoped {
|
||||
val resultBuffer = allocFfiReturnValueBuffer<ULongVar>(ULongVar)
|
||||
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_UINT64, args, null, memScope)
|
||||
resultBuffer.value
|
||||
}
|
||||
|
||||
@ExportForCompiler
|
||||
private fun invokeImplFloatRet(ptr: COpaquePointer, vararg args: Any?): Float = memScoped {
|
||||
val resultBuffer = allocFfiReturnValueBuffer<FloatVar>(FloatVar)
|
||||
|
||||
@@ -28,12 +28,23 @@ external fun bitsToFloat(bits: Int): Float
|
||||
@Intrinsic
|
||||
external fun bitsToDouble(bits: Long): Double
|
||||
|
||||
// TODO: deprecate.
|
||||
@Intrinsic
|
||||
external fun <R : Number> Number.signExtend(): R
|
||||
|
||||
// TODO: deprecate.
|
||||
@Intrinsic
|
||||
external fun <R : Number> Number.narrow(): R
|
||||
|
||||
@Intrinsic external fun <R : Any> Byte.convert(): R
|
||||
@Intrinsic external fun <R : Any> Short.convert(): R
|
||||
@Intrinsic external fun <R : Any> Int.convert(): R
|
||||
@Intrinsic external fun <R : Any> Long.convert(): R
|
||||
@Intrinsic external fun <R : Any> UByte.convert(): R
|
||||
@Intrinsic external fun <R : Any> UShort.convert(): R
|
||||
@Intrinsic external fun <R : Any> UInt.convert(): R
|
||||
@Intrinsic external fun <R : Any> ULong.convert(): R
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
internal annotation class JvmName(val name: String)
|
||||
@@ -56,6 +56,19 @@ fun IntArray.refTo(index: Int): CValuesRef<IntVar> = this.usingPinned { addressO
|
||||
fun Pinned<LongArray>.addressOf(index: Int): CPointer<LongVar> = this.addressOfElement(index)
|
||||
fun LongArray.refTo(index: Int): CValuesRef<LongVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
// TODO: pinning of unsigned arrays involves boxing as they are inline classes wrapping signed arrays.
|
||||
fun Pinned<UByteArray>.addressOf(index: Int): CPointer<UByteVar> = this.get().addressOfElement(index)
|
||||
fun UByteArray.refTo(index: Int): CValuesRef<UByteVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
fun Pinned<UShortArray>.addressOf(index: Int): CPointer<UShortVar> = this.get().addressOfElement(index)
|
||||
fun UShortArray.refTo(index: Int): CValuesRef<UShortVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
fun Pinned<UIntArray>.addressOf(index: Int): CPointer<UIntVar> = this.get().addressOfElement(index)
|
||||
fun UIntArray.refTo(index: Int): CValuesRef<UIntVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
fun Pinned<ULongArray>.addressOf(index: Int): CPointer<ULongVar> = this.get().addressOfElement(index)
|
||||
fun ULongArray.refTo(index: Int): CValuesRef<ULongVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
fun Pinned<FloatArray>.addressOf(index: Int): CPointer<FloatVar> = this.addressOfElement(index)
|
||||
fun FloatArray.refTo(index: Int): CValuesRef<FloatVar> = this.usingPinned { addressOf(index) }
|
||||
|
||||
@@ -79,3 +92,15 @@ private external fun getAddressOfElement(array: Any, index: Int): COpaquePointer
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun <P : CVariable> Pinned<*>.addressOfElement(index: Int): CPointer<P> =
|
||||
getAddressOfElement(this.get(), index).reinterpret()
|
||||
|
||||
@SymbolName("Kotlin_Arrays_getAddressOfElement")
|
||||
private external fun UByteArray.addressOfElement(index: Int): CPointer<UByteVar>
|
||||
|
||||
@SymbolName("Kotlin_Arrays_getAddressOfElement")
|
||||
private external fun UShortArray.addressOfElement(index: Int): CPointer<UShortVar>
|
||||
|
||||
@SymbolName("Kotlin_Arrays_getAddressOfElement")
|
||||
private external fun UIntArray.addressOfElement(index: Int): CPointer<UIntVar>
|
||||
|
||||
@SymbolName("Kotlin_Arrays_getAddressOfElement")
|
||||
private external fun ULongArray.addressOfElement(index: Int): CPointer<ULongVar>
|
||||
|
||||
@@ -30,11 +30,15 @@ const val FFI_TYPE_KIND_SINT64: FfiTypeKind = 4
|
||||
const val FFI_TYPE_KIND_FLOAT: FfiTypeKind = 5
|
||||
const val FFI_TYPE_KIND_DOUBLE: FfiTypeKind = 6
|
||||
const val FFI_TYPE_KIND_POINTER: FfiTypeKind = 7
|
||||
const val FFI_TYPE_KIND_UINT8: FfiTypeKind = 8
|
||||
const val FFI_TYPE_KIND_UINT16: FfiTypeKind = 9
|
||||
const val FFI_TYPE_KIND_UINT32: FfiTypeKind = 10
|
||||
const val FFI_TYPE_KIND_UINT64: FfiTypeKind = 11
|
||||
|
||||
private tailrec fun convertArgument(
|
||||
argument: Any?, isVariadic: Boolean, location: COpaquePointer,
|
||||
additionalPlacement: AutofreeScope
|
||||
): FfiTypeKind = when (argument) {
|
||||
): FfiTypeKind = when (argument) { // FIXME: optimize
|
||||
is CValuesRef<*>? -> {
|
||||
location.reinterpret<CPointerVar<*>>()[0] = argument?.getPointer(additionalPlacement)
|
||||
FFI_TYPE_KIND_POINTER
|
||||
@@ -79,6 +83,30 @@ private tailrec fun convertArgument(
|
||||
FFI_TYPE_KIND_SINT16
|
||||
}
|
||||
|
||||
is UInt -> {
|
||||
location.reinterpret<UIntVar>()[0] = argument
|
||||
FFI_TYPE_KIND_UINT32
|
||||
}
|
||||
|
||||
is ULong -> {
|
||||
location.reinterpret<ULongVar>()[0] = argument
|
||||
FFI_TYPE_KIND_UINT64
|
||||
}
|
||||
|
||||
is UByte -> if (isVariadic) {
|
||||
convertArgument(argument.toUInt(), isVariadic, location, additionalPlacement)
|
||||
} else {
|
||||
location.reinterpret<UByteVar>()[0] = argument
|
||||
FFI_TYPE_KIND_UINT8
|
||||
}
|
||||
|
||||
is UShort -> if (isVariadic) {
|
||||
convertArgument(argument.toUInt(), isVariadic, location, additionalPlacement)
|
||||
} else {
|
||||
location.reinterpret<UShortVar>()[0] = argument
|
||||
FFI_TYPE_KIND_UINT16
|
||||
}
|
||||
|
||||
is Double -> {
|
||||
location.reinterpret<DoubleVar>()[0] = argument
|
||||
FFI_TYPE_KIND_DOUBLE
|
||||
|
||||
+4
@@ -162,6 +162,10 @@ object KotlinTypes {
|
||||
val short by BuiltInType
|
||||
val int by BuiltInType
|
||||
val long by BuiltInType
|
||||
val uByte by BuiltInType
|
||||
val uShort by BuiltInType
|
||||
val uInt by BuiltInType
|
||||
val uLong by BuiltInType
|
||||
val float by BuiltInType
|
||||
val double by BuiltInType
|
||||
val unit by BuiltInType
|
||||
|
||||
+51
-29
@@ -23,8 +23,12 @@ interface DeclarationMapper {
|
||||
fun isMappedToStrict(enumDef: EnumDef): Boolean
|
||||
fun getKotlinNameForValue(enumDef: EnumDef): String
|
||||
fun getPackageFor(declaration: TypeDeclaration): String
|
||||
|
||||
val useUnsignedTypes: Boolean
|
||||
}
|
||||
|
||||
fun DeclarationMapper.isMappedToSigned(integerType: IntegerType): Boolean = integerType.isSigned || !useUnsignedTypes
|
||||
|
||||
fun DeclarationMapper.getKotlinClassFor(
|
||||
objCClassOrProtocol: ObjCClassOrProtocol,
|
||||
isMeta: Boolean = false
|
||||
@@ -41,38 +45,46 @@ fun DeclarationMapper.getKotlinClassFor(
|
||||
return Classifier.topLevel(pkg, className)
|
||||
}
|
||||
|
||||
val PrimitiveType.kotlinType: KotlinClassifierType
|
||||
get() = when (this) {
|
||||
is CharType -> KotlinTypes.byte
|
||||
fun PrimitiveType.getKotlinType(declarationMapper: DeclarationMapper): KotlinClassifierType = when (this) {
|
||||
is CharType -> KotlinTypes.byte
|
||||
|
||||
is BoolType -> KotlinTypes.boolean
|
||||
is BoolType -> KotlinTypes.boolean
|
||||
|
||||
// TODO: C primitive types should probably be generated as type aliases for Kotlin types.
|
||||
is IntegerType -> when (this.size) {
|
||||
// TODO: C primitive types should probably be generated as type aliases for Kotlin types.
|
||||
is IntegerType -> if (declarationMapper.isMappedToSigned(this)) {
|
||||
when (this.size) {
|
||||
1 -> KotlinTypes.byte
|
||||
2 -> KotlinTypes.short
|
||||
4 -> KotlinTypes.int
|
||||
8 -> KotlinTypes.long
|
||||
else -> TODO(this.toString())
|
||||
}
|
||||
|
||||
is FloatingType -> when (this.size) {
|
||||
4 -> KotlinTypes.float
|
||||
8 -> KotlinTypes.double
|
||||
} else {
|
||||
when (this.size) {
|
||||
1 -> KotlinTypes.uByte
|
||||
2 -> KotlinTypes.uShort
|
||||
4 -> KotlinTypes.uInt
|
||||
8 -> KotlinTypes.uLong
|
||||
else -> TODO(this.toString())
|
||||
}
|
||||
|
||||
else -> throw NotImplementedError()
|
||||
}
|
||||
|
||||
private val PrimitiveType.bridgedType: BridgedType
|
||||
get() {
|
||||
val kotlinType = this.kotlinType
|
||||
return BridgedType.values().single {
|
||||
it.kotlinType == kotlinType
|
||||
}
|
||||
is FloatingType -> when (this.size) {
|
||||
4 -> KotlinTypes.float
|
||||
8 -> KotlinTypes.double
|
||||
else -> TODO(this.toString())
|
||||
}
|
||||
|
||||
else -> throw NotImplementedError()
|
||||
}
|
||||
|
||||
private fun PrimitiveType.getBridgedType(declarationMapper: DeclarationMapper): BridgedType {
|
||||
val kotlinType = this.getKotlinType(declarationMapper)
|
||||
return BridgedType.values().single {
|
||||
it.kotlinType == kotlinType
|
||||
}
|
||||
}
|
||||
|
||||
internal val ObjCPointer.isNullable: Boolean
|
||||
get() = this.nullability != ObjCPointer.Nullability.NonNull
|
||||
|
||||
@@ -334,16 +346,26 @@ sealed class TypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
fun mirrorPrimitiveType(type: PrimitiveType): TypeMirror.ByValue {
|
||||
fun mirrorPrimitiveType(type: PrimitiveType, declarationMapper: DeclarationMapper): TypeMirror.ByValue {
|
||||
val varClassName = when (type) {
|
||||
is CharType -> "ByteVar"
|
||||
is BoolType -> "BooleanVar"
|
||||
is IntegerType -> when (type.size) {
|
||||
1 -> "ByteVar"
|
||||
2 -> "ShortVar"
|
||||
4 -> "IntVar"
|
||||
8 -> "LongVar"
|
||||
else -> TODO(type.toString())
|
||||
is IntegerType -> if (declarationMapper.isMappedToSigned(type)) {
|
||||
when (type.size) {
|
||||
1 -> "ByteVar"
|
||||
2 -> "ShortVar"
|
||||
4 -> "IntVar"
|
||||
8 -> "LongVar"
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
} else {
|
||||
when (type.size) {
|
||||
1 -> "UByteVar"
|
||||
2 -> "UShortVar"
|
||||
4 -> "UIntVar"
|
||||
8 -> "ULongVar"
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
}
|
||||
is FloatingType -> when (type.size) {
|
||||
4 -> "FloatVar"
|
||||
@@ -359,9 +381,9 @@ fun mirrorPrimitiveType(type: PrimitiveType): TypeMirror.ByValue {
|
||||
val info = if (type == BoolType) {
|
||||
TypeInfo.Boolean()
|
||||
} else {
|
||||
TypeInfo.Primitive(type.bridgedType, varClassOf)
|
||||
TypeInfo.Primitive(type.getBridgedType(declarationMapper), varClassOf)
|
||||
}
|
||||
return TypeMirror.ByValue(varClass.type, info, type.kotlinType)
|
||||
return TypeMirror.ByValue(varClass.type, info, type.getKotlinType(declarationMapper))
|
||||
}
|
||||
|
||||
private fun byRefTypeMirror(pointedType: KotlinClassifierType) : TypeMirror.ByRef {
|
||||
@@ -370,7 +392,7 @@ private fun byRefTypeMirror(pointedType: KotlinClassifierType) : TypeMirror.ByRe
|
||||
}
|
||||
|
||||
fun mirror(declarationMapper: DeclarationMapper, type: Type): TypeMirror = when (type) {
|
||||
is PrimitiveType -> mirrorPrimitiveType(type)
|
||||
is PrimitiveType -> mirrorPrimitiveType(type, declarationMapper)
|
||||
|
||||
is RecordType -> byRefTypeMirror(declarationMapper.getKotlinClassForPointed(type.decl).type)
|
||||
|
||||
@@ -380,7 +402,7 @@ fun mirror(declarationMapper: DeclarationMapper, type: Type): TypeMirror = when
|
||||
|
||||
when {
|
||||
declarationMapper.isMappedToStrict(type.def) -> {
|
||||
val bridgedType = (type.def.baseType.unwrapTypedefs() as PrimitiveType).bridgedType
|
||||
val bridgedType = (type.def.baseType.unwrapTypedefs() as PrimitiveType).getBridgedType(declarationMapper)
|
||||
val clazz = Classifier.topLevel(pkg, kotlinName)
|
||||
val info = TypeInfo.Enum(clazz, bridgedType)
|
||||
TypeMirror.ByValue(clazz.nested("Var").type, info, clazz.type)
|
||||
|
||||
+4
@@ -24,6 +24,10 @@ enum class BridgedType(val kotlinType: KotlinClassifierType, val convertor: Stri
|
||||
SHORT(KotlinTypes.short, "toShort"),
|
||||
INT(KotlinTypes.int, "toInt"),
|
||||
LONG(KotlinTypes.long, "toLong"),
|
||||
UBYTE(KotlinTypes.uByte, "toUByte"),
|
||||
USHORT(KotlinTypes.uShort, "toUShort"),
|
||||
UINT(KotlinTypes.uInt, "toUInt"),
|
||||
ULONG(KotlinTypes.uLong, "toULong"),
|
||||
FLOAT(KotlinTypes.float, "toFloat"),
|
||||
DOUBLE(KotlinTypes.double, "toDouble"),
|
||||
NATIVE_PTR(KotlinTypes.nativePtr),
|
||||
|
||||
+8
@@ -38,6 +38,10 @@ class SimpleBridgeGeneratorImpl(
|
||||
BridgedType.SHORT -> "jshort"
|
||||
BridgedType.INT -> "jint"
|
||||
BridgedType.LONG -> "jlong"
|
||||
BridgedType.UBYTE -> "jbyte"
|
||||
BridgedType.USHORT -> "jshort"
|
||||
BridgedType.UINT -> "jint"
|
||||
BridgedType.ULONG -> "jlong"
|
||||
BridgedType.FLOAT -> "jfloat"
|
||||
BridgedType.DOUBLE -> "jdouble"
|
||||
BridgedType.NATIVE_PTR -> "jlong"
|
||||
@@ -49,6 +53,10 @@ class SimpleBridgeGeneratorImpl(
|
||||
BridgedType.SHORT -> "int16_t"
|
||||
BridgedType.INT -> "int32_t"
|
||||
BridgedType.LONG -> "int64_t"
|
||||
BridgedType.UBYTE -> "uint8_t"
|
||||
BridgedType.USHORT -> "uint16_t"
|
||||
BridgedType.UINT -> "uint32_t"
|
||||
BridgedType.ULONG -> "uint64_t"
|
||||
BridgedType.FLOAT -> "float"
|
||||
BridgedType.DOUBLE -> "double"
|
||||
BridgedType.NATIVE_PTR -> "void*"
|
||||
|
||||
+31
-11
@@ -156,6 +156,12 @@ class StubGenerator(
|
||||
override fun getPackageFor(declaration: TypeDeclaration): String {
|
||||
return imports.getPackage(declaration.location) ?: pkgName
|
||||
}
|
||||
|
||||
override val useUnsignedTypes: Boolean
|
||||
get() = when (platform) {
|
||||
KotlinPlatform.JVM -> false
|
||||
KotlinPlatform.NATIVE -> true
|
||||
}
|
||||
}
|
||||
|
||||
fun mirror(type: Type): TypeMirror = mirror(declarationMapper, type)
|
||||
@@ -472,7 +478,8 @@ class StubGenerator(
|
||||
|
||||
block("enum class ${kotlinFile.declare(clazz)}(override val value: $baseKotlinType) : CEnum") {
|
||||
canonicalConstants.forEach {
|
||||
out("${it.name.asSimpleName()}(${it.value}),")
|
||||
val literal = integerLiteral(e.baseType, it.value)!!
|
||||
out("${it.name.asSimpleName()}($literal),")
|
||||
}
|
||||
out(";")
|
||||
out("")
|
||||
@@ -720,20 +727,33 @@ class StubGenerator(
|
||||
}
|
||||
|
||||
private fun integerLiteral(type: Type, value: Long): String? {
|
||||
val integerType = type.unwrapTypedefs() as? IntegerType ?: return null
|
||||
return integerLiteral(integerType.size, declarationMapper.isMappedToSigned(integerType), value)
|
||||
}
|
||||
|
||||
private fun integerLiteral(size: Int, isSigned: Boolean, value: Long): String? {
|
||||
if (!isSigned) {
|
||||
val signedLiteral = integerLiteral(size, true, value)
|
||||
val converter = when (size) {
|
||||
1 -> "toUByte"
|
||||
2 -> "toUShort"
|
||||
4 -> "toUInt"
|
||||
8 -> "toULong"
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return "($signedLiteral).$converter()"
|
||||
}
|
||||
|
||||
if (value == Long.MIN_VALUE) {
|
||||
return "${value + 1} - 1" // Workaround for "The value is out of range" compile error.
|
||||
}
|
||||
|
||||
val unwrappedType = type.unwrapTypedefs()
|
||||
if (unwrappedType !is PrimitiveType) {
|
||||
return null
|
||||
}
|
||||
|
||||
val narrowedValue: Number = when (unwrappedType.kotlinType) {
|
||||
KotlinTypes.byte -> value.toByte()
|
||||
KotlinTypes.short -> value.toShort()
|
||||
KotlinTypes.int -> value.toInt()
|
||||
KotlinTypes.long -> value
|
||||
val narrowedValue: Number = when (size) {
|
||||
1 -> value.toByte()
|
||||
2 -> value.toShort()
|
||||
4 -> value.toInt()
|
||||
8 -> value
|
||||
else -> return null
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.cli.bc
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.AnalysisFlag
|
||||
|
||||
class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
// First go the options interesting to the general public.
|
||||
@@ -147,5 +149,11 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
description = "Paths to friend modules"
|
||||
)
|
||||
var friendModules: String? = null
|
||||
|
||||
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> =
|
||||
super.configureAnalysisFlags(collector).also {
|
||||
val useExperimental = it[AnalysisFlag.useExperimental] as List<*>
|
||||
it[AnalysisFlag.useExperimental] = useExperimental + listOf("kotlin.ExperimentalUnsignedTypes")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.descriptors.konan.interop.InteropFqNames
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -90,6 +92,8 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
||||
|
||||
val narrow = packageScope.getContributedFunctions("narrow").single()
|
||||
|
||||
val convert = packageScope.getContributedFunctions("convert").toSet()
|
||||
|
||||
val readBits = packageScope.getContributedFunctions("readBits").single()
|
||||
val writeBits = packageScope.getContributedFunctions("writeBits").single()
|
||||
|
||||
@@ -101,6 +105,9 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
||||
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == cPointer
|
||||
}.toSet()
|
||||
|
||||
private fun KonanBuiltIns.getUnsignedClass(unsignedType: UnsignedType): ClassDescriptor =
|
||||
this.builtInsModule.findClassAcrossModuleDependencies(unsignedType.classId)!!
|
||||
|
||||
val invokeImpls = mapOf(
|
||||
builtIns.unit to "invokeImplUnitRet",
|
||||
builtIns.boolean to "invokeImplBooleanRet",
|
||||
@@ -108,6 +115,10 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
||||
builtIns.short to "invokeImplShortRet",
|
||||
builtIns.int to "invokeImplIntRet",
|
||||
builtIns.long to "invokeImplLongRet",
|
||||
builtIns.getUnsignedClass(UnsignedType.UBYTE) to "invokeImplUByteRet",
|
||||
builtIns.getUnsignedClass(UnsignedType.USHORT) to "invokeImplUShortRet",
|
||||
builtIns.getUnsignedClass(UnsignedType.UINT) to "invokeImplUIntRet",
|
||||
builtIns.getUnsignedClass(UnsignedType.ULONG) to "invokeImplULongRet",
|
||||
builtIns.float to "invokeImplFloatRet",
|
||||
builtIns.double to "invokeImplDoubleRet",
|
||||
cPointer to "invokeImplPointerRet"
|
||||
|
||||
+29
@@ -144,6 +144,35 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
val uInt = unsignedClass(UnsignedType.UINT)
|
||||
val uLong = unsignedClass(UnsignedType.ULONG)
|
||||
|
||||
val signedIntegerClasses = setOf(byte, short, int, long)
|
||||
val unsignedIntegerClasses = setOf(uByte, uShort, uInt, uLong)
|
||||
|
||||
val allIntegerClasses = signedIntegerClasses + unsignedIntegerClasses
|
||||
|
||||
val integerConversions = allIntegerClasses.flatMap { fromClass ->
|
||||
allIntegerClasses.map { toClass ->
|
||||
val name = Name.identifier("to${toClass.descriptor.name.asString().capitalize()}")
|
||||
val descriptor = if (fromClass in signedIntegerClasses && toClass in unsignedIntegerClasses) {
|
||||
builtInsPackage("kotlin")
|
||||
.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
|
||||
.single {
|
||||
it.dispatchReceiverParameter == null &&
|
||||
it.extensionReceiverParameter?.type == fromClass.descriptor.defaultType &&
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
} else {
|
||||
fromClass.descriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
|
||||
.single {
|
||||
it.extensionReceiverParameter == null && it.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
val symbol = symbolTable.referenceSimpleFunction(descriptor)
|
||||
|
||||
(fromClass to toClass) to symbol
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
|
||||
|
||||
val interopNativePointedGetRawPointer =
|
||||
|
||||
+35
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -901,6 +902,35 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
}
|
||||
|
||||
in interop.convert -> {
|
||||
val integerClasses = symbols.allIntegerClasses
|
||||
val typeOperand = expression.getTypeArgument(0)!!
|
||||
val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type
|
||||
val receiverClass = receiverType.classifierOrFail as IrClassSymbol
|
||||
assert(receiverClass in integerClasses)
|
||||
|
||||
if (typeOperand is IrSimpleType && typeOperand.classifier in integerClasses && !typeOperand.hasQuestionMark) {
|
||||
val typeOperandClass = typeOperand.classifier as IrClassSymbol
|
||||
|
||||
val conversion = symbols.integerConversions[receiverClass to typeOperandClass]!!.owner
|
||||
|
||||
builder.irCall(conversion).apply {
|
||||
val valueToConvert = expression.extensionReceiver!!
|
||||
if (conversion.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = valueToConvert
|
||||
} else {
|
||||
extensionReceiver = valueToConvert
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.reportCompilationError(
|
||||
"unable to convert ${receiverType.toKotlinType()} to ${typeOperand.toKotlinType()}",
|
||||
irFile,
|
||||
expression
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
in interop.cFunctionPointerInvokes -> {
|
||||
// Replace by `invokeImpl${type}Ret`:
|
||||
|
||||
@@ -968,6 +998,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
return
|
||||
}
|
||||
|
||||
if (UnsignedTypes.isUnsignedType(this.toKotlinType()) && !this.containsNull()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.getClass()?.descriptor == interop.cPointer) {
|
||||
return
|
||||
}
|
||||
@@ -976,7 +1010,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
|
||||
private fun IrType.checkCTypeNullability(reportError: (String) -> Nothing) {
|
||||
if (this.isNullablePrimitiveType()) {
|
||||
if (this.isNullablePrimitiveType() || UnsignedTypes.isUnsignedType(this.toKotlinType()) && this.containsNull()) {
|
||||
reportError("Type ${this.toKotlinType()} must not be nullable when used in C function signature")
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ fun main(args: Array<String>) {
|
||||
val values = intArrayOf(14, 12, 9, 13, 8)
|
||||
val count = values.size
|
||||
|
||||
cstdlib.qsort(values.refTo(0), count.toLong(), IntVar.size, staticCFunction { a, b ->
|
||||
cstdlib.qsort(values.refTo(0), count.toULong(), IntVar.size.convert(), staticCFunction { a, b ->
|
||||
val aValue = a!!.reinterpret<IntVar>()[0]
|
||||
val bValue = b!!.reinterpret<IntVar>()[0]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ fun assertEquals(value1: Any?, value2: Any?) {
|
||||
throw AssertionError("Expected $value1, got $value2")
|
||||
}
|
||||
|
||||
fun check(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
fun check(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long) {
|
||||
assertEquals(x1, s.x1)
|
||||
assertEquals(x1, getX1(s.ptr))
|
||||
|
||||
@@ -26,7 +26,7 @@ fun check(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
assertEquals(x6, getX6(s.ptr))
|
||||
}
|
||||
|
||||
fun assign(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
fun assign(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long) {
|
||||
s.x1 = x1
|
||||
s.x2 = x2
|
||||
s.x3 = x3
|
||||
@@ -35,7 +35,7 @@ fun assign(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
s.x6 = x6
|
||||
}
|
||||
|
||||
fun assignReversed(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
fun assignReversed(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long) {
|
||||
s.x6 = x6
|
||||
s.x5 = x5
|
||||
s.x4 = x4
|
||||
@@ -44,7 +44,7 @@ fun assignReversed(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long
|
||||
s.x1 = x1
|
||||
}
|
||||
|
||||
fun test(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
fun test(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long) {
|
||||
assign(s, x1, x2, x3, x4, x5, x6)
|
||||
check(s, x1, x2, x3, x4, x5, x6)
|
||||
|
||||
@@ -53,10 +53,10 @@ fun test(s: S, x1: Long, x2: B2, x3: Short, x4: Int, x5: Int, x6: Long) {
|
||||
|
||||
// Also check with some insignificant bits modified:
|
||||
|
||||
assign(s, x1 + 2, x2, (x3 + 8).toShort(), x4 - 16, x5 + 32, x6 + Long.MIN_VALUE)
|
||||
assign(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE)
|
||||
check(s, x1, x2, x3, x4, x5, x6)
|
||||
|
||||
assignReversed(s, x1 + 2, x2, (x3 + 8).toShort(), x4 - 16, x5 + 32, x6 + Long.MIN_VALUE)
|
||||
assignReversed(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE)
|
||||
check(s, x1, x2, x3, x4, x5, x6)
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ fun main(args: Array<String>) {
|
||||
for (x1 in -1L..0L)
|
||||
for (x2 in B2.values())
|
||||
for (x3 in 0..7)
|
||||
for (x4 in intArrayOf(0, 6, 15))
|
||||
for (x4 in uintArrayOf(0u, 6u, 15u))
|
||||
for (x5 in intArrayOf(-16, -2, -1, 0, 5, 15))
|
||||
for (x6 in longArrayOf(Long.MIN_VALUE/2, -1L shl 36, -325L, 0, 1L shl 48, Long.MAX_VALUE/2))
|
||||
test(s, x1, x2, x3.toShort(), x4, x5, x6)
|
||||
test(s, x1, x2, x3.toUShort(), x4, x5, x6)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,12 @@ typedef _Bool (*isIntPositivePtrType)(int);
|
||||
|
||||
static isIntPositivePtrType getIsIntPositivePtr() {
|
||||
return &__isIntPositive;
|
||||
}
|
||||
|
||||
static unsigned int getMaxUInt(void) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static typeof(&getMaxUInt) getMaxUIntGetter() {
|
||||
return &getMaxUInt;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ fun main(args: Array<String>) {
|
||||
return
|
||||
}
|
||||
|
||||
val port = atoi(args[0]).toShort()
|
||||
val port = atoi(args[0]).toUShort()
|
||||
|
||||
memScoped {
|
||||
|
||||
@@ -19,13 +19,13 @@ fun main(args: Array<String>) {
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
|
||||
with(serverAddr) {
|
||||
memset(this.ptr, 0, sockaddr_in.size)
|
||||
sin_family = AF_INET.narrow()
|
||||
sin_addr.s_addr = htons(0).toInt()
|
||||
memset(this.ptr, 0, sockaddr_in.size.convert())
|
||||
sin_family = AF_INET.convert()
|
||||
sin_addr.s_addr = htons(0u).convert()
|
||||
sin_port = htons(port)
|
||||
}
|
||||
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt())
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toUInt())
|
||||
.ensureUnixCallResult { it == 0 }
|
||||
|
||||
listen(listenFd, 10)
|
||||
@@ -35,21 +35,21 @@ fun main(args: Array<String>) {
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
|
||||
while (true) {
|
||||
val length = read(commFd, buffer, bufferLength)
|
||||
val length = read(commFd, buffer, bufferLength.convert())
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
|
||||
if (length == 0L) {
|
||||
break
|
||||
}
|
||||
|
||||
write(commFd, buffer, length)
|
||||
write(commFd, buffer, length.convert())
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not available through interop because declared as macro:
|
||||
fun htons(value: Short) = ((value.toInt() ushr 8) or (value.toInt() shl 8)).toShort()
|
||||
fun htons(value: UShort) = ((value.toInt() ushr 8) or (value.toInt() shl 8)).toUShort()
|
||||
|
||||
fun throwUnixError(): Nothing {
|
||||
perror(null) // TODO: store error message to exception instead.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import kotlinx.cinterop.*
|
||||
import cfunptr.*
|
||||
import kotlin.test.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val atoiPtr = getAtoiPtr()!!
|
||||
@@ -23,6 +24,8 @@ fun main(args: Array<String>) {
|
||||
|
||||
printIntPtr(isIntPositivePtr(42).ifThenOneElseZero())
|
||||
printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero())
|
||||
|
||||
assertEquals(getMaxUIntGetter()!!(), UInt.MAX_VALUE)
|
||||
}
|
||||
|
||||
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
|
||||
@@ -13,7 +13,7 @@ private val windowHeight = 480
|
||||
|
||||
fun display() {
|
||||
// Clear Screen and Depth Buffer
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).convert())
|
||||
glLoadIdentity()
|
||||
|
||||
// Define a viewing transformation
|
||||
@@ -40,13 +40,13 @@ fun display() {
|
||||
|
||||
fun initialize() {
|
||||
// select projection matrix
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glMatrixMode(GL_PROJECTION.convert())
|
||||
|
||||
// set the viewport
|
||||
glViewport(0, 0, windowWidth, windowHeight)
|
||||
|
||||
// set matrix mode
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glMatrixMode(GL_PROJECTION.convert())
|
||||
|
||||
// reset projection matrix
|
||||
glLoadIdentity()
|
||||
@@ -56,29 +56,29 @@ fun initialize() {
|
||||
gluPerspective(45.0, aspect, 1.0, 500.0)
|
||||
|
||||
// specify which matrix is the current matrix
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glMatrixMode(GL_MODELVIEW.convert())
|
||||
glShadeModel(GL_SMOOTH.convert())
|
||||
|
||||
// specify the clear value for the depth buffer
|
||||
glClearDepth(1.0)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glDepthFunc(GL_LEQUAL)
|
||||
glEnable(GL_DEPTH_TEST.convert())
|
||||
glDepthFunc(GL_LEQUAL.convert())
|
||||
|
||||
// specify implementation-specific hints
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT.convert(), GL_NICEST.convert())
|
||||
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cValuesOf(0.1f, 0.1f, 0.1f, 1.0f))
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, cValuesOf(0.6f, 0.6f, 0.6f, 1.0f))
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, cValuesOf(0.7f, 0.7f, 0.3f, 1.0f))
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT.convert(), cValuesOf(0.1f, 0.1f, 0.1f, 1.0f))
|
||||
glLightfv(GL_LIGHT0.convert(), GL_DIFFUSE.convert(), cValuesOf(0.6f, 0.6f, 0.6f, 1.0f))
|
||||
glLightfv(GL_LIGHT0.convert(), GL_SPECULAR.convert(), cValuesOf(0.7f, 0.7f, 0.3f, 1.0f))
|
||||
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_COLOR_MATERIAL)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)
|
||||
glDepthFunc(GL_LEQUAL)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_LIGHT0.convert())
|
||||
glEnable(GL_COLOR_MATERIAL.convert())
|
||||
glShadeModel(GL_SMOOTH.convert())
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE.convert(), GL_FALSE)
|
||||
glDepthFunc(GL_LEQUAL.convert())
|
||||
glEnable(GL_DEPTH_TEST.convert())
|
||||
glEnable(GL_LIGHTING.convert())
|
||||
glEnable(GL_LIGHT0.convert())
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
|
||||
// Display Mode
|
||||
glutInitDisplayMode(GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH)
|
||||
glutInitDisplayMode((GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH).convert())
|
||||
|
||||
// Set window size
|
||||
glutInitWindowSize(windowWidth, windowHeight)
|
||||
|
||||
@@ -22,8 +22,8 @@ fun main(args: Array<String>) {
|
||||
val destPtr = alloc<CArrayPointerVar<ByteVar>>()
|
||||
destPtr.value = destBytes
|
||||
|
||||
sourceLength.value = sourceByteArray.size.signExtend();
|
||||
destLength.value = golden.size.signExtend();
|
||||
sourceLength.value = sourceByteArray.size.convert()
|
||||
destLength.value = golden.size.convert()
|
||||
|
||||
val conversion = iconv_open("UTF-8", "LATIN1")
|
||||
|
||||
|
||||
@@ -118,9 +118,9 @@ fun testTypeOps() {
|
||||
assertTrue(NSValue.asAny() is NSObjectProtocolMeta)
|
||||
assertFalse(NSValue.asAny() is NSObjectProtocol) // Must be true, but not implemented properly yet.
|
||||
|
||||
assertEquals(3, ("foo" as NSString).length())
|
||||
assertEquals(4, ((1..4).joinToString("") as NSString).length())
|
||||
assertEquals(2, (listOf(0, 1) as NSArray).count())
|
||||
assertEquals(3u, ("foo" as NSString).length())
|
||||
assertEquals(4u, ((1..4).joinToString("") as NSString).length())
|
||||
assertEquals(2u, (listOf(0, 1) as NSArray).count())
|
||||
assertEquals(42L, (42 as NSNumber).longLongValue())
|
||||
|
||||
assertFails { "bar" as NSNumber }
|
||||
|
||||
@@ -2,7 +2,7 @@ import kotlinx.cinterop.*
|
||||
|
||||
import platform.zlib.*
|
||||
|
||||
val source = immutableBlobOf(0xF3, 0x48, 0xCD, 0xC9, 0xC9, 0x57, 0x04, 0x00).asCPointer()
|
||||
val source = immutableBlobOf(0xF3, 0x48, 0xCD, 0xC9, 0xC9, 0x57, 0x04, 0x00).asCPointer().reinterpret<UByteVar>()
|
||||
val golden = immutableBlobOf(0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21, 0x00).asCPointer()
|
||||
|
||||
fun main(args: Array<String>) = memScoped {
|
||||
@@ -10,9 +10,9 @@ fun main(args: Array<String>) = memScoped {
|
||||
buffer.usePinned { pinned ->
|
||||
val z = alloc<z_stream>().apply {
|
||||
next_in = source
|
||||
avail_in = 8
|
||||
next_out = pinned.addressOf(0)
|
||||
avail_out = buffer.size
|
||||
avail_in = 8u
|
||||
next_out = pinned.addressOf(0).reinterpret()
|
||||
avail_out = buffer.size.toUInt()
|
||||
}.ptr
|
||||
|
||||
if (inflateInit2(z, -15) == Z_OK && inflate(z, Z_FINISH) == Z_STREAM_END && inflateEnd(z) == Z_OK)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import kotlinx.cinterop.signExtend
|
||||
import kotlinx.cinterop.convert
|
||||
import platform.posix.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
// Just check the typealias is in scope.
|
||||
val sizet: size_t = 0.signExtend<size_t>()
|
||||
val sizet: size_t = 0.convert<size_t>()
|
||||
println("sizet = $sizet")
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import kotlinx.cinterop.signExtend
|
||||
import kotlinx.cinterop.convert
|
||||
import platform.posix.*
|
||||
|
||||
fun foo() {
|
||||
println("linked library")
|
||||
val size: size_t = 17.signExtend<size_t>()
|
||||
val size: size_t = 17.convert<size_t>()
|
||||
val e = fabs(1.toDouble())
|
||||
println("and symbols from posix available: $size; $e")
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ const FfiTypeKind FFI_TYPE_KIND_SINT64 = 4;
|
||||
const FfiTypeKind FFI_TYPE_KIND_FLOAT = 5;
|
||||
const FfiTypeKind FFI_TYPE_KIND_DOUBLE = 6;
|
||||
const FfiTypeKind FFI_TYPE_KIND_POINTER = 7;
|
||||
const FfiTypeKind FFI_TYPE_KIND_UINT8 = 8;
|
||||
const FfiTypeKind FFI_TYPE_KIND_UINT16 = 9;
|
||||
const FfiTypeKind FFI_TYPE_KIND_UINT32 = 10;
|
||||
const FfiTypeKind FFI_TYPE_KIND_UINT64 = 11;
|
||||
|
||||
ffi_type* convertFfiTypeKindToType(FfiTypeKind typeKind) {
|
||||
switch (typeKind) {
|
||||
@@ -51,6 +55,10 @@ ffi_type* convertFfiTypeKindToType(FfiTypeKind typeKind) {
|
||||
case FFI_TYPE_KIND_FLOAT: return &ffi_type_float;
|
||||
case FFI_TYPE_KIND_DOUBLE: return &ffi_type_double;
|
||||
case FFI_TYPE_KIND_POINTER: return &ffi_type_pointer;
|
||||
case FFI_TYPE_KIND_UINT8: return &ffi_type_uint8;
|
||||
case FFI_TYPE_KIND_UINT16: return &ffi_type_uint16;
|
||||
case FFI_TYPE_KIND_UINT32: return &ffi_type_uint32;
|
||||
case FFI_TYPE_KIND_UINT64: return &ffi_type_uint64;
|
||||
|
||||
default: assert(false); return nullptr;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ fun CPointer<ByteVar>.toKString(length: Int): String {
|
||||
}
|
||||
|
||||
fun header_callback(buffer: CPointer<ByteVar>?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t {
|
||||
if (buffer == null) return 0
|
||||
if (buffer == null) return 0u
|
||||
if (userdata != null) {
|
||||
val header = buffer.toKString((size * nitems).toInt()).trim()
|
||||
val curl = userdata.asStableRef<CUrl>().get()
|
||||
@@ -56,7 +56,7 @@ fun header_callback(buffer: CPointer<ByteVar>?, size: size_t, nitems: size_t, us
|
||||
|
||||
|
||||
fun write_callback(buffer: CPointer<ByteVar>?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t {
|
||||
if (buffer == null) return 0
|
||||
if (buffer == null) return 0u
|
||||
if (userdata != null) {
|
||||
val data = buffer.toKString((size * nitems).toInt()).trim()
|
||||
val curl = userdata.asStableRef<CUrl>().get()
|
||||
|
||||
@@ -32,11 +32,11 @@ class GitCommit(val repository: GitRepository, val commit: CPointer<git_commit>)
|
||||
}
|
||||
|
||||
val parents: List<GitCommit> get() = memScoped {
|
||||
val count = git_commit_parentcount(commit)
|
||||
val count = git_commit_parentcount(commit).toInt()
|
||||
val result = ArrayList<GitCommit>(count)
|
||||
for (index in 0..count - 1) {
|
||||
val commitPtr = allocPointerTo<git_commit>()
|
||||
git_commit_parent(commitPtr.ptr, commit, index).errorCheck()
|
||||
git_commit_parent(commitPtr.ptr, commit, index.toUInt()).errorCheck()
|
||||
result.add(GitCommit(repository, commitPtr.value!!))
|
||||
}
|
||||
result
|
||||
|
||||
@@ -21,10 +21,10 @@ import libgit2.*
|
||||
|
||||
class GitDiff(val repository: GitRepository, val handle: CPointer<git_diff>) {
|
||||
fun deltas(): List<GifDiffDelta> {
|
||||
val size = git_diff_num_deltas(handle)
|
||||
val results = ArrayList<GifDiffDelta>(size.toInt())
|
||||
val size = git_diff_num_deltas(handle).toInt()
|
||||
val results = ArrayList<GifDiffDelta>(size)
|
||||
for (index in 0..size - 1) {
|
||||
val delta = git_diff_get_delta(handle, index)
|
||||
val delta = git_diff_get_delta(handle, index.convert())
|
||||
results.add(GifDiffDelta(this, delta!!))
|
||||
}
|
||||
return results
|
||||
|
||||
@@ -23,10 +23,10 @@ class GitTree(val repository: GitRepository, val handle: CPointer<git_tree>) {
|
||||
fun close() = git_tree_free(handle)
|
||||
|
||||
fun entries(): List<GitTreeEntry> = memScoped {
|
||||
val size = git_tree_entrycount(handle)
|
||||
val entries = ArrayList<GitTreeEntry>(size.toInt())
|
||||
val size = git_tree_entrycount(handle).toInt()
|
||||
val entries = ArrayList<GitTreeEntry>(size)
|
||||
for (index in 0..size - 1) {
|
||||
val treeEntry = git_tree_entry_byindex(handle, index)!!
|
||||
val treeEntry = git_tree_entry_byindex(handle, index.convert())!!
|
||||
val entryType = git_tree_entry_type(treeEntry)
|
||||
val entry = when (entryType) {
|
||||
GIT_OBJ_TREE -> memScoped {
|
||||
|
||||
@@ -19,7 +19,7 @@ import gtk3.*
|
||||
|
||||
// Note that all callback parameters must be primitive types or nullable C pointers.
|
||||
fun <F : CFunction<*>> g_signal_connect(obj: CPointer<*>, actionName: String,
|
||||
action: CPointer<F>, data: gpointer? = null, connect_flags: Int = 0) {
|
||||
action: CPointer<F>, data: gpointer? = null, connect_flags: GConnectFlags = 0u) {
|
||||
g_signal_connect_data(obj.reinterpret(), actionName, action.reinterpret(),
|
||||
data = data, destroy_data = null, connect_flags = connect_flags)
|
||||
|
||||
|
||||
@@ -32,16 +32,16 @@ fun main(args: Array<String>) {
|
||||
val serverAddr = alloc<sockaddr_in>()
|
||||
|
||||
val listenFd = socket(AF_INET, SOCK_STREAM, 0)
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
.ensureUnixCallResult { !it.isMinusOne() }
|
||||
|
||||
with(serverAddr) {
|
||||
memset(this.ptr, 0, sockaddr_in.size)
|
||||
sin_family = AF_INET.narrow()
|
||||
sin_addr.s_addr = posix_htons(0).toInt()
|
||||
sin_port = posix_htons(port)
|
||||
memset(this.ptr, 0, sockaddr_in.size.convert())
|
||||
sin_family = AF_INET.convert()
|
||||
sin_addr.s_addr = posix_htons(0).convert()
|
||||
sin_port = posix_htons(port).convert()
|
||||
}
|
||||
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt())
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toUInt())
|
||||
.ensureUnixCallResult { it == 0 }
|
||||
|
||||
fcntl(listenFd, F_SETFL, O_NONBLOCK)
|
||||
@@ -53,8 +53,8 @@ fun main(args: Array<String>) {
|
||||
var connectionId = 0
|
||||
acceptClientsAndRun(listenFd) {
|
||||
memScoped {
|
||||
val bufferLength = 100L
|
||||
val buffer = allocArray<ByteVar>(bufferLength)
|
||||
val bufferLength = 100uL
|
||||
val buffer = allocArray<ByteVar>(bufferLength.toLong())
|
||||
val connectionIdString = "#${++connectionId}: ".cstr
|
||||
val connectionIdBytes = connectionIdString.ptr
|
||||
|
||||
@@ -62,10 +62,10 @@ fun main(args: Array<String>) {
|
||||
while (true) {
|
||||
val length = read(buffer, bufferLength)
|
||||
|
||||
if (length == 0L)
|
||||
if (length == 0uL)
|
||||
break
|
||||
|
||||
write(connectionIdBytes, connectionIdString.size.toLong())
|
||||
write(connectionIdBytes, connectionIdString.size.toULong())
|
||||
write(buffer, length)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
@@ -80,19 +80,19 @@ sealed class WaitingFor {
|
||||
class Accept : WaitingFor()
|
||||
|
||||
class Read(val data: CArrayPointer<ByteVar>,
|
||||
val length: Long,
|
||||
val continuation: Continuation<Long>) : WaitingFor()
|
||||
val length: ULong,
|
||||
val continuation: Continuation<ULong>) : WaitingFor()
|
||||
|
||||
class Write(val data: CArrayPointer<ByteVar>,
|
||||
val length: Long,
|
||||
val length: ULong,
|
||||
val continuation: Continuation<Unit>) : WaitingFor()
|
||||
}
|
||||
|
||||
class Client(val clientFd: Int, val waitingList: MutableMap<Int, WaitingFor>) {
|
||||
suspend fun read(data: CArrayPointer<ByteVar>, dataLength: Long): Long {
|
||||
suspend fun read(data: CArrayPointer<ByteVar>, dataLength: ULong): ULong {
|
||||
val length = read(clientFd, data, dataLength)
|
||||
if (length >= 0)
|
||||
return length
|
||||
return length.toULong()
|
||||
if (posix_errno() != EWOULDBLOCK)
|
||||
throw IOException(getUnixError())
|
||||
// Save continuation and suspend.
|
||||
@@ -101,7 +101,7 @@ class Client(val clientFd: Int, val waitingList: MutableMap<Int, WaitingFor>) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun write(data: CArrayPointer<ByteVar>, length: Long) {
|
||||
suspend fun write(data: CArrayPointer<ByteVar>, length: ULong) {
|
||||
val written = write(clientFd, data, length)
|
||||
if (written >= 0)
|
||||
return
|
||||
@@ -153,7 +153,7 @@ fun acceptClientsAndRun(serverFd: Int, block: suspend Client.() -> Unit) {
|
||||
|
||||
// Accept new client.
|
||||
val clientFd = accept(serverFd, null, null)
|
||||
if (clientFd < 0) {
|
||||
if (clientFd.isMinusOne()) {
|
||||
if (posix_errno() != EWOULDBLOCK)
|
||||
throw Error(getUnixError())
|
||||
break@loop
|
||||
@@ -173,7 +173,7 @@ fun acceptClientsAndRun(serverFd: Int, block: suspend Client.() -> Unit) {
|
||||
val length = read(socketFd, waitingFor.data, waitingFor.length)
|
||||
if (length < 0) // Read error.
|
||||
waitingFor.continuation.resumeWithException(IOException(getUnixError()))
|
||||
waitingFor.continuation.resume(length)
|
||||
waitingFor.continuation.resume(length.toULong())
|
||||
}
|
||||
is WaitingFor.Write -> {
|
||||
if (errorOccured)
|
||||
@@ -210,3 +210,14 @@ inline fun Long.ensureUnixCallResult(predicate: (Long) -> Boolean): Long {
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun ULong.ensureUnixCallResult(predicate: (ULong) -> Boolean): ULong {
|
||||
if (!predicate(this)) {
|
||||
throw Error(getUnixError())
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun Int.isMinusOne() = (this == -1)
|
||||
private fun Long.isMinusOne() = (this == -1L)
|
||||
private fun ULong.isMinusOne() = (this == ULong.MAX_VALUE)
|
||||
|
||||
@@ -24,7 +24,7 @@ private fun runApp() {
|
||||
app.run()
|
||||
}
|
||||
|
||||
data class Data(val stamp: Long)
|
||||
data class Data(val stamp: ULong)
|
||||
|
||||
private class Controller : NSObject() {
|
||||
private val asyncQueue = dispatch_queue_create("com.jetbrains.CustomQueue", null)
|
||||
@@ -33,7 +33,7 @@ private class Controller : NSObject() {
|
||||
fun onClick() {
|
||||
// Execute some async action on button click.
|
||||
dispatch_async_f(asyncQueue, detachObjectGraph {
|
||||
Data(clock_gettime_nsec_np(CLOCK_REALTIME))
|
||||
Data(clock_gettime_nsec_np(CLOCK_REALTIME.convert()))
|
||||
}, staticCFunction {
|
||||
it ->
|
||||
initRuntimeIfNeeded()
|
||||
|
||||
@@ -29,7 +29,7 @@ private val windowHeight = 480
|
||||
|
||||
fun display() {
|
||||
// Clear Screen and Depth Buffer
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).convert())
|
||||
glLoadIdentity()
|
||||
|
||||
// Define a viewing transformation
|
||||
@@ -56,13 +56,13 @@ fun display() {
|
||||
|
||||
fun initialize() {
|
||||
// select projection matrix
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glMatrixMode(GL_PROJECTION.convert())
|
||||
|
||||
// set the viewport
|
||||
glViewport(0, 0, windowWidth, windowHeight)
|
||||
|
||||
// set matrix mode
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glMatrixMode(GL_PROJECTION.convert())
|
||||
|
||||
// reset projection matrix
|
||||
glLoadIdentity()
|
||||
@@ -72,29 +72,29 @@ fun initialize() {
|
||||
gluPerspective(45.0, aspect, 1.0, 500.0)
|
||||
|
||||
// specify which matrix is the current matrix
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glMatrixMode(GL_MODELVIEW.convert())
|
||||
glShadeModel(GL_SMOOTH.convert())
|
||||
|
||||
// specify the clear value for the depth buffer
|
||||
glClearDepth(1.0)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glDepthFunc(GL_LEQUAL)
|
||||
glEnable(GL_DEPTH_TEST.convert())
|
||||
glDepthFunc(GL_LEQUAL.convert())
|
||||
|
||||
// specify implementation-specific hints
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT.convert(), GL_NICEST.convert())
|
||||
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cValuesOf(0.1f, 0.1f, 0.1f, 1.0f))
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, cValuesOf(0.6f, 0.6f, 0.6f, 1.0f))
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, cValuesOf(0.7f, 0.7f, 0.3f, 1.0f))
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT.convert(), cValuesOf(0.1f, 0.1f, 0.1f, 1.0f))
|
||||
glLightfv(GL_LIGHT0.convert(), GL_DIFFUSE.convert(), cValuesOf(0.6f, 0.6f, 0.6f, 1.0f))
|
||||
glLightfv(GL_LIGHT0.convert(), GL_SPECULAR.convert(), cValuesOf(0.7f, 0.7f, 0.3f, 1.0f))
|
||||
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_COLOR_MATERIAL)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)
|
||||
glDepthFunc(GL_LEQUAL)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_LIGHT0.convert())
|
||||
glEnable(GL_COLOR_MATERIAL.convert())
|
||||
glShadeModel(GL_SMOOTH.convert())
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE.convert(), GL_FALSE)
|
||||
glDepthFunc(GL_LEQUAL.convert())
|
||||
glEnable(GL_DEPTH_TEST.convert())
|
||||
glEnable(GL_LIGHTING.convert())
|
||||
glEnable(GL_LIGHT0.convert())
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
|
||||
// Display Mode
|
||||
glutInitDisplayMode(GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH)
|
||||
glutInitDisplayMode((GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH).convert())
|
||||
|
||||
// Set window size
|
||||
glutInitWindowSize(windowWidth, windowHeight)
|
||||
|
||||
@@ -35,35 +35,35 @@ fun main(args: Array<String>) {
|
||||
val serverAddr = alloc<sockaddr_in>()
|
||||
|
||||
val listenFd = socket(AF_INET, SOCK_STREAM, 0)
|
||||
.ensureUnixCallResult("socket") { it >= 0 }
|
||||
.ensureUnixCallResult("socket") { !it.isMinusOne() }
|
||||
|
||||
with(serverAddr) {
|
||||
memset(this.ptr, 0, sockaddr_in.size)
|
||||
sin_family = AF_INET.narrow()
|
||||
sin_port = posix_htons(port)
|
||||
memset(this.ptr, 0, sockaddr_in.size.convert())
|
||||
sin_family = AF_INET.convert()
|
||||
sin_port = posix_htons(port).convert()
|
||||
}
|
||||
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt())
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.convert())
|
||||
.ensureUnixCallResult("bind") { it == 0 }
|
||||
|
||||
listen(listenFd, 10)
|
||||
.ensureUnixCallResult("listen") { it == 0 }
|
||||
|
||||
val commFd = accept(listenFd, null, null)
|
||||
.ensureUnixCallResult("accept") { it >= 0 }
|
||||
.ensureUnixCallResult("accept") { !it.isMinusOne() }
|
||||
|
||||
buffer.usePinned { pinned ->
|
||||
while (true) {
|
||||
val length = recv(commFd, pinned.addressOf(0), buffer.size.signExtend(), 0).toInt()
|
||||
val length = recv(commFd, pinned.addressOf(0), buffer.size.convert(), 0).toInt()
|
||||
.ensureUnixCallResult("read") { it >= 0 }
|
||||
|
||||
if (length == 0) {
|
||||
break
|
||||
}
|
||||
|
||||
send(commFd, prefixBuffer.refTo(0), prefixBuffer.size.signExtend(), 0)
|
||||
send(commFd, prefixBuffer.refTo(0), prefixBuffer.size.convert(), 0)
|
||||
.ensureUnixCallResult("write") { it >= 0 }
|
||||
send(commFd, pinned.addressOf(0), length.signExtend(), 0)
|
||||
send(commFd, pinned.addressOf(0), length.convert(), 0)
|
||||
.ensureUnixCallResult("write") { it >= 0 }
|
||||
}
|
||||
}
|
||||
@@ -83,3 +83,14 @@ inline fun Long.ensureUnixCallResult(op: String, predicate: (Long) -> Boolean):
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun ULong.ensureUnixCallResult(op: String, predicate: (ULong) -> Boolean): ULong {
|
||||
if (!predicate(this)) {
|
||||
throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun Int.isMinusOne() = (this == -1)
|
||||
private fun Long.isMinusOne() = (this == -1L)
|
||||
private fun ULong.isMinusOne() = (this == ULong.MAX_VALUE)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.size_t
|
||||
import tensorflow.*
|
||||
|
||||
typealias Status = CPointer<TF_Status>
|
||||
@@ -31,13 +32,13 @@ fun scalarTensor(value: Int): Tensor {
|
||||
|
||||
return TF_NewTensor(TF_INT32,
|
||||
dims = null, num_dims = 0,
|
||||
data = data, len = IntVar.size,
|
||||
data = data, len = IntVar.size.convert(),
|
||||
deallocator = staticCFunction { dataToFree, _, _ -> nativeHeap.free(dataToFree!!.reinterpret<IntVar>()) },
|
||||
deallocator_arg = null)!!
|
||||
}
|
||||
|
||||
val Tensor.scalarIntValue: Int get() {
|
||||
if (TF_INT32 != TF_TensorType(this) || IntVar.size != TF_TensorByteSize(this)) {
|
||||
if (TF_INT32 != TF_TensorType(this) || IntVar.size.convert<size_t>() != TF_TensorByteSize(this)) {
|
||||
throw Error("Tensor is not of type int.")
|
||||
}
|
||||
if (0 != TF_NumDims(this)) {
|
||||
|
||||
@@ -42,13 +42,13 @@ class AudioFrame(val buffer: CPointer<AVBufferRef>, var position: Int, val size:
|
||||
private fun Int.checkAVError() {
|
||||
if (this != 0) {
|
||||
val buffer = ByteArray(1024)
|
||||
av_strerror(this, buffer.refTo(0), buffer.size.signExtend())
|
||||
av_strerror(this, buffer.refTo(0), buffer.size.convert())
|
||||
throw Error("AVError: ${buffer.stringFromUtf8()}")
|
||||
}
|
||||
}
|
||||
|
||||
private val AVFormatContext.codecs: List<AVCodecContext?>
|
||||
get() = List(nb_streams) { streams?.get(it)?.pointed?.codec?.pointed }
|
||||
get() = List(nb_streams.toInt()) { streams?.get(it)?.pointed?.codec?.pointed }
|
||||
|
||||
private fun AVFormatContext.streamAt(index: Int): AVStream? =
|
||||
if (index < 0) null else streams?.get(index)?.pointed
|
||||
@@ -124,7 +124,7 @@ private class VideoDecoder(
|
||||
dispose = ::sws_freeContext
|
||||
)
|
||||
private val scaledFrameSize = avpicture_get_size(avPixelFormat, windowSize.w, windowSize.h)
|
||||
private val buffer: ByteArray = ByteArray(scaledFrameSize)
|
||||
private val buffer: UByteArray = UByteArray(scaledFrameSize) { 0u }
|
||||
|
||||
private val videoQueue = Queue<VideoFrame>(100)
|
||||
|
||||
@@ -158,7 +158,7 @@ private class VideoDecoder(
|
||||
val buffer = av_buffer_alloc(scaledFrameSize)!!
|
||||
val ts = av_frame_get_best_effort_timestamp(videoFrame.ptr) *
|
||||
av_q2d(videoCodecContext.time_base.readValue())
|
||||
memcpy(buffer.pointed.data, scaledVideoFrame.data[0], scaledFrameSize.signExtend())
|
||||
memcpy(buffer.pointed.data, scaledVideoFrame.data[0], scaledFrameSize.convert())
|
||||
videoQueue.push(VideoFrame(buffer, scaledVideoFrame.linesize[0], ts))
|
||||
}
|
||||
}
|
||||
@@ -204,11 +204,11 @@ private class AudioDecoder(
|
||||
channels = output.channels
|
||||
sample_rate = output.sampleRate
|
||||
format = output.sampleFormat
|
||||
channel_layout = output.channelLayout.signExtend()
|
||||
channel_layout = output.channelLayout.convert()
|
||||
}
|
||||
|
||||
with (audioCodecContext) {
|
||||
setResampleOpt("in_channel_layout", channel_layout.narrow())
|
||||
setResampleOpt("in_channel_layout", channel_layout.convert())
|
||||
setResampleOpt("out_channel_layout", output.channelLayout)
|
||||
setResampleOpt("in_sample_rate", sample_rate)
|
||||
setResampleOpt("out_sample_rate", output.sampleRate)
|
||||
@@ -255,7 +255,7 @@ private class AudioDecoder(
|
||||
val buffer = av_buffer_alloc(audioFrameSize)!!
|
||||
val ts = av_frame_get_best_effort_timestamp(audioFrame.ptr) *
|
||||
av_q2d(audioCodecContext.time_base.readValue())
|
||||
memcpy(buffer.pointed.data, data[0], audioFrameSize.signExtend())
|
||||
memcpy(buffer.pointed.data, data[0], audioFrameSize.convert())
|
||||
audioQueue.push(AudioFrame(buffer, 0, audioFrameSize, ts))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ enum class SampleFormat {
|
||||
data class AudioOutput(val sampleRate: Int, val channels: Int, val sampleFormat: SampleFormat)
|
||||
|
||||
private fun SampleFormat.toSDLFormat(): SDL_AudioFormat? = when (this) {
|
||||
SampleFormat.S16 -> AUDIO_S16SYS.narrow()
|
||||
SampleFormat.S16 -> AUDIO_S16SYS.convert()
|
||||
SampleFormat.INVALID -> null
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ class SDLAudio(val player: VideoPlayer) : DisposableContainer() {
|
||||
val spec = alloc<SDL_AudioSpec>().apply {
|
||||
freq = audio.sampleRate
|
||||
format = audioFormat
|
||||
channels = audio.channels.narrow()
|
||||
silence = 0
|
||||
samples = 4096
|
||||
channels = audio.channels.convert()
|
||||
silence = 0u
|
||||
samples = 4096u
|
||||
userdata = threadData
|
||||
callback = staticCFunction(::audioCallback)
|
||||
}
|
||||
@@ -89,12 +89,12 @@ private fun audioCallback(userdata: COpaquePointer?, buffer: CPointer<Uint8Var>?
|
||||
val frame = decoder.nextAudioFrame(length - outPosition)
|
||||
if (frame != null) {
|
||||
val toCopy = minOf(length - outPosition, frame.size - frame.position)
|
||||
memcpy(buffer + outPosition, frame.buffer.pointed.data + frame.position, toCopy.signExtend())
|
||||
memcpy(buffer + outPosition, frame.buffer.pointed.data + frame.position, toCopy.convert())
|
||||
frame.unref()
|
||||
outPosition += toCopy
|
||||
} else {
|
||||
// println("Decoder returned nothing!")
|
||||
memset(buffer + outPosition, 0, (length - outPosition).signExtend())
|
||||
memset(buffer + outPosition, 0, (length - outPosition).convert())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class SDLRendererWindow(windowPos: Dimensions, videoSize: Dimensions) : Disposab
|
||||
SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), 0, videoSize.w, videoSize.h),
|
||||
::SDL_DestroyTexture)
|
||||
private val rect = sdlDisposable("calloc(SDL_Rect)",
|
||||
SDL_calloc(1, SDL_Rect.size), ::SDL_free)
|
||||
SDL_calloc(1u, SDL_Rect.size.convert()), ::SDL_free)
|
||||
.reinterpret<SDL_Rect>()
|
||||
|
||||
init {
|
||||
|
||||
@@ -71,7 +71,7 @@ class VideoPlayer(val requestedSize: Dimensions?) : DisposableContainer() {
|
||||
}
|
||||
|
||||
private fun getTime(): Double {
|
||||
clock_gettime(platform.posix.CLOCK_MONOTONIC, now)
|
||||
clock_gettime(platform.posix.CLOCK_MONOTONIC.convert(), now)
|
||||
return now.pointed.tv_sec + now.pointed.tv_nsec / 1e9
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ class VideoPlayer(val requestedSize: Dimensions?) : DisposableContainer() {
|
||||
lastFrameTime += frameDuration // try to maintain perfect frame rate
|
||||
// Wait for next frame, if needed
|
||||
if (passedTime < frameDuration) {
|
||||
usleep((1000_000 * (frameDuration - passedTime)).toInt())
|
||||
usleep((1000_000 * (frameDuration - passedTime)).toInt().toUInt())
|
||||
} else if (passedTime > frameDuration * 1.5){
|
||||
lastFrameTime = now // we fell behind more than half frame, reset time
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class VideoPlayer(val requestedSize: Dimensions?) : DisposableContainer() {
|
||||
while (state == State.PAUSED) {
|
||||
audio.pause()
|
||||
input.check()
|
||||
usleep(1 * 1000)
|
||||
usleep(1u * 1000u)
|
||||
}
|
||||
audio.resume()
|
||||
}
|
||||
@@ -152,14 +152,14 @@ class VideoPlayer(val requestedSize: Dimensions?) : DisposableContainer() {
|
||||
if (!decoder.audioVideoSynced()) {
|
||||
println("Resynchronizing video with audio")
|
||||
while (!decoder.audioVideoSynced() && state == State.PLAYING) {
|
||||
usleep(500)
|
||||
usleep(500u)
|
||||
input.check()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For pure sound, playback is driven by demand.
|
||||
usleep(10 * 1000)
|
||||
usleep(10u * 1000u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import kotlinx.cinterop.*
|
||||
import platform.windows.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
MessageBoxW(null, "Konan говорит:\nЗДРАВСТВУЙ МИР!\n",
|
||||
"Заголовок окна", MB_YESNOCANCEL or MB_ICONQUESTION)
|
||||
"Заголовок окна", (MB_YESNOCANCEL or MB_ICONQUESTION).convert())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user