seraphyの日記

日記というよりは過去を振り返るときのための単なる備忘録

JDK6のScriptingでjythonを呼び出してみる

準備と利用

まず、scripting.dev.java.netから、jsr223-engines.zipをもらってきて展開する。(ドキュメントのリンクからアーカイブにたどり着ける)
この中にScriptEngineFactoryがいっぱいあるので、その中のjythonjython-engine.jarをクラスパスに追加。
jython本体は含まれていないので、jython.jarは別途必要で、これもクラスパスに通しておく。

    final ScriptEngineManager engMgr = new ScriptEngineManager();
    for (final ScriptEngineFactory factory : engMgr.getEngineFactories()) {
        System.out.println("*engine=" + factory.getEngineName());
        for (final String name : factory.getNames()) {
            System.out.println("name=" + name);
        }
    }

こんな感じで利用可能なスクリプトエンジンが増えているのが確認できる。
結果は、

*engine=Mozilla Rhino
name=js
name=rhino
name=JavaScript
name=javascript
name=ECMAScript
name=ecmascript
*engine=jython
name=jython
name=python

jythonの場合は名前で索引するならば、「jython」「python」で取得できるようだ。

ためしに

    final ScriptEngineManager engMgr = new ScriptEngineManager();
    final ScriptEngine eng = engMgr.getEngineByName("jython");
    eng.eval("def f(x):\n\treturn x + 1");
    final Object ret = ((Invocable) eng).invokeFunction("f", 100);
    System.out.println(ret);
    System.out.println(ret.getClass());

とやって、結果は、

101
class java.lang.Integer

で、成功。

JavaScriptで定義したファンクションをjythonで使うことができるか試してみる。

    final ScriptEngineManager engMgr = new ScriptEngineManager();
    final ScriptEngine eng1 = engMgr.getEngineByName("js");
    eng1.eval("function f(x) {return x+1;}");
    final ScriptContext ctx = eng1.getContext();

    final ScriptEngine eng2 = engMgr.getEngineByName("jython");
    eng2.setContext(ctx);
    eng2.eval("print f(1);");

結果は、

Exception in thread "main" javax.script.ScriptException: Traceback (innermost last):
  File "<unknown>", line 1, in ?
AttributeError: instance of 'sun.org.mozilla.javascript.internal.InterpretedFunction' has no attribute '__call__'

        at com.sun.script.jython.JythonScriptEngine.evalCode(JythonScriptEngine.java:292)
        at com.sun.script.jython.JythonScriptEngine.eval(JythonScriptEngine.java:170)
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)

で失敗。

うーん、__call__ねェ。
たしかに、pythonは、そんなものが必要かもねー。
一応、オブジェクトがあることは認識してるみたいだけど。


Javaからスクリプト言語のファンクションをうまい具合に呼び出せるのに、スクリプト間で呼び出せないのもヘンだな。
なにか方法がありそうな気がする。


とりあえず、今日はここまで。
以上、おわり。