mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
ffi: support for java native functions
This commit is contained in:
@ -0,0 +1,20 @@
|
||||
package gay.pizza.pork.ffi
|
||||
|
||||
class FfiFunctionDefinition(
|
||||
val library: String,
|
||||
val function: String,
|
||||
val returnType: String
|
||||
) {
|
||||
companion object {
|
||||
fun parse(def: String): FfiFunctionDefinition {
|
||||
val parts = def.split(":", limit = 3)
|
||||
if (parts.size != 3 || parts.any { it.trim().isEmpty() }) {
|
||||
throw RuntimeException(
|
||||
"FFI function definition is invalid, " +
|
||||
"excepted format is 'library:function:return-type' but '${def}' was specified")
|
||||
}
|
||||
val (library, function, returnType) = parts
|
||||
return FfiFunctionDefinition(library, function, returnType)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package gay.pizza.pork.ffi
|
||||
|
||||
class JavaFunctionDefinition(
|
||||
val type: String,
|
||||
val kind: String,
|
||||
val symbol: String,
|
||||
val returnType: String,
|
||||
val parameters: List<String>
|
||||
) {
|
||||
companion object {
|
||||
fun parse(def: String): JavaFunctionDefinition {
|
||||
val parts = def.split(":", limit = 5)
|
||||
if (!(parts.size == 4 || parts.size == 5) || parts.any { it.trim().isEmpty() }) {
|
||||
throw RuntimeException(
|
||||
"Java function definition is invalid, " +
|
||||
"excepted format is 'type:kind:symbol:return-type:(optional)parameters' but '${def}' was specified")
|
||||
}
|
||||
val (type, kind, symbol, returnType) = parts
|
||||
val parameters = if (parts.size > 4) parts[4].split(",") else emptyList()
|
||||
return JavaFunctionDefinition(type, kind, symbol, returnType, parameters)
|
||||
}
|
||||
}
|
||||
}
|
42
ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt
Normal file
42
ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt
Normal file
@ -0,0 +1,42 @@
|
||||
package gay.pizza.pork.ffi
|
||||
|
||||
import gay.pizza.pork.evaluator.CallableFunction
|
||||
import gay.pizza.pork.evaluator.NativeFunctionProvider
|
||||
import gay.pizza.pork.evaluator.None
|
||||
import java.lang.invoke.MethodHandles
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
class JavaNativeProvider : NativeFunctionProvider {
|
||||
private val lookup = MethodHandles.lookup()
|
||||
|
||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
||||
val functionDefinition = JavaFunctionDefinition.parse(definition)
|
||||
val javaClass = lookupClass(functionDefinition.type)
|
||||
val returnTypeClass = lookupClass(functionDefinition.returnType)
|
||||
val parameterClasses = functionDefinition.parameters.map { lookup.findClass(it) }
|
||||
val handle = mapKindToHandle(
|
||||
functionDefinition.kind,
|
||||
functionDefinition.symbol,
|
||||
javaClass,
|
||||
returnTypeClass,
|
||||
parameterClasses
|
||||
)
|
||||
return CallableFunction { arguments -> handle.invokeWithArguments(arguments.values) ?: None }
|
||||
}
|
||||
|
||||
private fun lookupClass(name: String): Class<*> = when (name) {
|
||||
"void" -> Void.TYPE
|
||||
else -> lookup.findClass(name)
|
||||
}
|
||||
|
||||
private fun mapKindToHandle(kind: String, symbol: String, javaClass: Class<*>, returnType: Class<*>, parameterTypes: List<Class<*>>) = when (kind) {
|
||||
"getter" -> lookup.findGetter(javaClass, symbol, returnType)
|
||||
"setter" -> lookup.findSetter(javaClass, symbol, returnType)
|
||||
"constructor" -> lookup.findConstructor(javaClass, MethodType.methodType(returnType, parameterTypes))
|
||||
"static" -> lookup.findStatic(javaClass, symbol, MethodType.methodType(returnType, parameterTypes))
|
||||
"virtual" -> lookup.findVirtual(javaClass, symbol, MethodType.methodType(returnType, parameterTypes))
|
||||
"static-getter" -> lookup.findStaticGetter(javaClass, symbol, returnType)
|
||||
"static-setter" -> lookup.findStaticSetter(javaClass, symbol, returnType)
|
||||
else -> throw RuntimeException("Unknown Handle Kind: $kind")
|
||||
}
|
||||
}
|
@ -6,11 +6,10 @@ import gay.pizza.pork.evaluator.NativeFunctionProvider
|
||||
|
||||
class JnaNativeProvider : NativeFunctionProvider {
|
||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
||||
val (libraryName, functionSymbol, returnType, _) =
|
||||
definition.split(":", limit = 3)
|
||||
val function = Function.getFunction(libraryName, functionSymbol)
|
||||
val functionDefinition = FfiFunctionDefinition.parse(definition)
|
||||
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
|
||||
return CallableFunction {
|
||||
return@CallableFunction invoke(function, it.values.toTypedArray(), returnType)
|
||||
return@CallableFunction invoke(function, it.values.toTypedArray(), functionDefinition.returnType)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user