native: pass argument specs in order to support varadic ffi

This commit is contained in:
2023-09-11 01:12:32 -04:00
parent 8d310e337a
commit 2ee1565fb5
7 changed files with 33 additions and 9 deletions

View File

@ -1,5 +1,6 @@
package gay.pizza.pork.ffi
import gay.pizza.pork.ast.ArgumentSpec
import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.evaluator.NativeProvider
import gay.pizza.pork.evaluator.None
@ -9,7 +10,7 @@ import java.lang.invoke.MethodType
class JavaNativeProvider : NativeProvider {
private val lookup = MethodHandles.lookup()
override fun provideNativeFunction(definition: String): CallableFunction {
override fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction {
val functionDefinition = JavaFunctionDefinition.parse(definition)
val javaClass = lookupClass(functionDefinition.type)
val returnTypeClass = lookupClass(functionDefinition.returnType)
@ -21,7 +22,7 @@ class JavaNativeProvider : NativeProvider {
returnTypeClass,
parameterClasses
)
return CallableFunction { arguments -> handle.invokeWithArguments(arguments.values) ?: None }
return CallableFunction { functionArguments -> handle.invokeWithArguments(functionArguments.values) ?: None }
}
private fun lookupClass(name: String): Class<*> = when (name) {

View File

@ -1,19 +1,31 @@
package gay.pizza.pork.ffi
import com.sun.jna.Function
import gay.pizza.pork.ast.ArgumentSpec
import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.evaluator.NativeProvider
class JnaNativeProvider : NativeProvider {
override fun provideNativeFunction(definition: String): CallableFunction {
override fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction {
val functionDefinition = FfiFunctionDefinition.parse(definition)
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
return CallableFunction {
invoke(function, it.values.toTypedArray(), functionDefinition.returnType)
return CallableFunction { functionArgs ->
val ffiArgs = mutableListOf<Any?>()
for ((index, spec) in arguments.withIndex()) {
if (spec.multiple) {
val variableArguments = functionArgs.values
.subList(index, functionArgs.values.size)
ffiArgs.addAll(variableArguments)
break
} else {
ffiArgs.add(functionArgs.values[index])
}
}
invoke(function, ffiArgs.toTypedArray(), functionDefinition.returnType)
}
}
private fun invoke(function: Function, values: Array<Any>, type: String): Any = when (type) {
private fun invoke(function: Function, values: Array<Any?>, type: String): Any = when (type) {
"void*" -> function.invokePointer(values)
"int" -> function.invokeInt(values)
"long" -> function.invokeLong(values)