mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
ffi: rework for future struct support
This commit is contained in:
parent
7cb3e02b21
commit
dacec08587
30
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt
Normal file
30
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
|
import gay.pizza.pork.evaluator.None
|
||||||
|
|
||||||
|
enum class FfiPrimitiveType(
|
||||||
|
val id: kotlin.String,
|
||||||
|
override val size: kotlin.Int,
|
||||||
|
val numberConvert: (Number.() -> Number)? = null,
|
||||||
|
val nullableConversion: (Any?.() -> Any)? = null,
|
||||||
|
val notNullConversion: (Any.() -> Any)? = null
|
||||||
|
) : FfiType {
|
||||||
|
Byte("byte", 1, numberConvert = { toByte() }),
|
||||||
|
UnsignedByte("unsigned byte", 1, numberConvert = { toByte()}),
|
||||||
|
Short("short", 2, numberConvert = { toShort() }),
|
||||||
|
UnsignedShort("unsigned short", 2, numberConvert = { toShort() }),
|
||||||
|
Int("int", 4, numberConvert = { toInt() }),
|
||||||
|
UnsignedInt("unsigned int", 4, numberConvert = { toInt() }),
|
||||||
|
Float("float", 4, numberConvert = { toFloat() }),
|
||||||
|
Long("long", 8, numberConvert = { toLong() }),
|
||||||
|
UnsignedLong("unsigned long", 8, numberConvert = { toLong() }),
|
||||||
|
Double("double", 8, numberConvert = { toDouble() }),
|
||||||
|
String("char*", 8, nullableConversion = { toString() }),
|
||||||
|
Pointer("void*", 8, nullableConversion = {
|
||||||
|
if (this is kotlin.Long) {
|
||||||
|
com.sun.jna.Pointer(this)
|
||||||
|
} else if (this == None) {
|
||||||
|
com.sun.jna.Pointer.NULL
|
||||||
|
} else this as com.sun.jna.Pointer
|
||||||
|
})
|
||||||
|
}
|
14
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt
Normal file
14
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
|
class FfiStruct : FfiType {
|
||||||
|
private val fields = mutableListOf<FfiStructField>()
|
||||||
|
|
||||||
|
data class FfiStructField(val name: String, val type: FfiType)
|
||||||
|
|
||||||
|
fun add(field: String, type: FfiType) {
|
||||||
|
fields.add(FfiStructField(field, type))
|
||||||
|
}
|
||||||
|
|
||||||
|
override val size: Int
|
||||||
|
get() = fields.sumOf { it.type.size }
|
||||||
|
}
|
5
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt
Normal file
5
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
|
interface FfiType {
|
||||||
|
val size: Int
|
||||||
|
}
|
@ -2,7 +2,6 @@ package gay.pizza.pork.ffi
|
|||||||
|
|
||||||
import com.sun.jna.Function
|
import com.sun.jna.Function
|
||||||
import com.sun.jna.NativeLibrary
|
import com.sun.jna.NativeLibrary
|
||||||
import com.sun.jna.Pointer
|
|
||||||
import gay.pizza.pork.ast.ArgumentSpec
|
import gay.pizza.pork.ast.ArgumentSpec
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.NativeProvider
|
import gay.pizza.pork.evaluator.NativeProvider
|
||||||
@ -48,24 +47,23 @@ class JnaNativeProvider : NativeProvider {
|
|||||||
else -> type
|
else -> type
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convert(type: String, value: Any?): Any? = when (rewriteType(type)) {
|
private fun convert(type: String, value: Any?): Any? {
|
||||||
"short" -> numberConvert(type, value) { toShort() }
|
val rewritten = rewriteType(type)
|
||||||
"unsigned short" -> numberConvert(type, value) { toShort() }
|
val primitive = FfiPrimitiveType.entries.firstOrNull { it.id == rewritten }
|
||||||
"int" -> numberConvert(type, value) { toInt() }
|
?: throw RuntimeException("Unsupported ffi type: $type")
|
||||||
"unsigned int" -> numberConvert(type, value) { toInt() }
|
if (primitive.numberConvert != null) {
|
||||||
"long" -> numberConvert(type, value) { toLong() }
|
return numberConvert(type, value, primitive.numberConvert)
|
||||||
"unsigned long" -> numberConvert(type, value) { toLong() }
|
|
||||||
"double" -> numberConvert(type, value) { toDouble() }
|
|
||||||
"float" -> numberConvert(type, value) { toFloat() }
|
|
||||||
"char*" -> notNullConvert(type, value) { toString() }
|
|
||||||
"void*" -> nullableConvert(value) {
|
|
||||||
if (value is Long) {
|
|
||||||
Pointer(value)
|
|
||||||
} else {
|
|
||||||
value as Pointer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> throw RuntimeException("Unsupported ffi type: $type")
|
|
||||||
|
if (primitive.notNullConversion != null) {
|
||||||
|
return notNullConvert(type, value, primitive.notNullConversion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primitive.nullableConversion != null) {
|
||||||
|
return nullableConvert(value, primitive.nullableConversion)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> notNullConvert(type: String, value: Any?, into: Any.() -> T): T {
|
private fun <T> notNullConvert(type: String, value: Any?, into: Any.() -> T): T {
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
org.gradle.warning.mode=none
|
org.gradle.warning.mode=none
|
||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
|
kotlin.experimental.tryK2=true
|
||||||
|
Loading…
Reference in New Issue
Block a user