我正在尝试Graalvm非常酷的Polyglot特性,这样我就可以从Scala应用程序中评估Python。
下面是测试REPL代码。如果我运行它,并输入以下代码,我可以很好地评估v.__add__(1)
。我得到了这个:
>>> v
evaluating v
evaluated got Value(7)
>>> v.__add__(1)
evaluating v.__add__(1)
evaluated got Value(8)
>>>
字符串
有什么方法可以计算v + 1
吗?我尝试的时候得到了TypeError: unsupported operand type(s) for +: 'foreign' and 'int'
。
下面是测试REPL代码:
import org.graalvm.polyglot.{Context, Source}
import scala.annotation.targetName
import scala.util.control.NonFatal
case class Value(v: Int) {
@targetName("__add__")
def +(i: Int): Value = Value(v + i)
}
class Python(context: Context, v: Value) {
private val language = "python"
context.getBindings(language).putMember("v", v)
def eval(code: String): AnyRef = {
try {
val source = Source
.newBuilder(language, code, "<shell>")
.interactive(false)
.buildLiteral()
println(s"evaluating $code")
val res = context.eval(source)
println(s"evaluated got $res")
res
} catch {
case NonFatal(e) =>
println(s"error evaluating $code")
e.printStackTrace()
null
}
}
}
object Python {
def main(args: Array[String]): Unit = {
val context = Context
.newBuilder("python")
.allowAllAccess(true)
.build()
val python = new Python(context, Value(7))
while (true) {
val line = scala.io.StdIn.readLine(">>> ")
python.eval(line)
}
}
}
型
1条答案
按热度按时间aiqt4smr1#
在这一点上,GraalPy不允许像这样覆盖Python的“魔法”方法。“Foreign”对象获取类“foreign”,它以一种方式defines一些“魔法”方法,它们调用适当的低级Truffle interop messages。你可以看到它们像这样:
字符串
问题是你的对象的Python类型不是Java/Scala类,而是“foreign”。你定义的方法和字段是属于对象示例的Python属性,但是像
+
这样的操作的“魔术”方法是在type =>“foreign”类型上查找的。参见https://github.com/oracle/graalpython/issues/249。目前,虽然你可以在Scalar/Java端实现较低级别的Truffle互操作消息,但我建议你尝试从“另一个”端来实现。你可以定义Python类来 Package Scala/Java对象,并适当地实现“神奇”方法:
型
你可以从Scala/Java中按照以下沿着示例化它:
型
也可以在Python中示例化它。