I'm trying to access a class defined in a script, evaluated with ScriptEngine.
Consider the following snippet:
package com.example
interface Foo
{
fun bar()
}
val script = """
import com.example.Foo
class MyFoo : Foo
{
override fun bar() = println("Hello from MyFoo::bar")
}
"""
fun main()
{
val scriptEngineManager = ScriptEngineManager()
val scriptEngine = scriptEngineManager.getEngineByName("kotlin")
scriptEngine.eval(script)
}
This runs successfully, and now I'd like to instantiate MyFoo in the host code.
The only way I've managed to do so successfully is by using ScriptEngine::eval to return a reference to the class, by evaluating an expression referencing it:
fun main()
{
val scriptEngineManager = ScriptEngineManager()
val scriptEngine = scriptEngineManager.getEngineByName("kotlin")
scriptEngine.eval(script)
// -- See below --
val fooKClass = scriptEngine.eval("MyFoo::class") as KClass<Foo>
val foo = fooKClass.createInstance()
foo.bar()
}
This too, runs successfullly, writing Hello from MyFoo::bar to standard out.
However, is there no way to add the script-defined class MyFoo to the host JVM classdefs?
fun main()
{
val scriptEngineManager = ScriptEngineManager()
val scriptEngine = scriptEngineManager.getEngineByName("kotlin")
scriptEngine.eval(script)
// -- See below --
val fooKClass = Class.forName("MyFoo").kotlin as KClass<Foo>
val foo = fooKClass.createInstance()
foo.bar()
}
The above predictably fails with a java.lang.ClassNotFoundException: MyFoo.
Is dynamically evaluating and returning (from the ScriptEngine) the Class<*> or KClass<*> instance the only way to access it from the host JVM?