ffi: rework for future struct support

This commit is contained in:
Alex Zenla 2023-09-18 04:53:24 -07:00
parent 7cb3e02b21
commit dacec08587
Signed by: alex
GPG Key ID: C0780728420EBFE5
5 changed files with 66 additions and 18 deletions

View 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
})
}

View 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 }
}

View File

@ -0,0 +1,5 @@
package gay.pizza.pork.ffi
interface FfiType {
val size: Int
}

View File

@ -2,7 +2,6 @@ package gay.pizza.pork.ffi
import com.sun.jna.Function
import com.sun.jna.NativeLibrary
import com.sun.jna.Pointer
import gay.pizza.pork.ast.ArgumentSpec
import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.evaluator.NativeProvider
@ -48,24 +47,23 @@ class JnaNativeProvider : NativeProvider {
else -> type
}
private fun convert(type: String, value: Any?): Any? = when (rewriteType(type)) {
"short" -> numberConvert(type, value) { toShort() }
"unsigned short" -> numberConvert(type, value) { toShort() }
"int" -> numberConvert(type, value) { toInt() }
"unsigned int" -> numberConvert(type, value) { toInt() }
"long" -> numberConvert(type, value) { toLong() }
"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
}
private fun convert(type: String, value: Any?): Any? {
val rewritten = rewriteType(type)
val primitive = FfiPrimitiveType.entries.firstOrNull { it.id == rewritten }
?: throw RuntimeException("Unsupported ffi type: $type")
if (primitive.numberConvert != null) {
return numberConvert(type, value, primitive.numberConvert)
}
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 {

View File

@ -1,2 +1,3 @@
org.gradle.warning.mode=none
kotlin.stdlib.default.dependency=false
kotlin.experimental.tryK2=true