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