なんとなくPythonの拡張を作ってみたくてこの2日間がんばってみた*1。Pythonを扱っているはずだけどC++しかやってないな、そういえば。
で、作ったものはpyjvmモジュールと名づけてみた。何をするものかというと、PythonからJavaVM (JNI関数) を呼ぶだけ。しかもJNIメソッド名ほぼそのままで。
このモジュールを使うと、こんな風にJNIを呼び出せます。
#-*- coding: utf-8 -*- import pyjvm jvm = pyjvm.JavaVM() clazz = jvm.findClass("java/lang/Math") doubleMaxMethod = jvm.getStaticMethod(clazz, "max", "(DD)D") floatMaxMethod = jvm.getStaticMethod(clazz, "max", "(FF)F") intMaxMethod = jvm.getStaticMethod(clazz, "max", "(II)I") longMaxMethod = jvm.getStaticMethod(clazz, "max", "(JJ)J") print jvm.callStaticDoubleMethod(clazz, doubleMaxMethod, (127.0, -127.0)) print jvm.callStaticFloatMethod(clazz, floatMaxMethod, (127.0, -127.0)) print jvm.callStaticIntMethod(clazz, intMaxMethod, (127, -127)) print jvm.callStaticLongMethod(clazz, longMaxMethod, (127, -127)) systemClass = jvm.findClass("java/lang/System") currentTimeMethod = jvm.getStaticMethod(systemClass, "currentTimeMillis", "()J") print jvm.callStaticLongMethod(systemClass, currentTimeMethod, ()), " [ms]"
まんまJNI関数を呼び出すので、異様にめんどう。でも実装は (関数があんまりないので) 楽かもしれない。
最初はstaticメソッドで終わろうかとも思ったけど、オブジェクトの生成とかも出来ないとダメかな、と思って実装した。結果JFrameを表示できるようになりました。
まぁ、こんなコード (なげぇ…)
#-*- coding: utf-8 -*- import pyjvm jvm = pyjvm.JavaVM() clazz = jvm.findClass("javax/swing/JFrame") constructor = jvm.getMethod(clazz, "<init>", "()V") titleMethod = jvm.getMethod(clazz, "setTitle", "(Ljava/lang/String;)V") visibleMethod = jvm.getMethod(clazz, "show", "()V") closeOperationMethod = jvm.getMethod(clazz, "setDefaultCloseOperation", "(I)V") sizeMethod = jvm.getMethod(clazz, "setSize", "(II)V") # ボタン btnClazz = jvm.findClass("javax/swing/JLabel") btnConstructor = jvm.getMethod(btnClazz, "<init>", "(Ljava/lang/String;)V") containerMethod = jvm.getMethod(clazz, "getContentPane", "()Ljava/awt/Container;") containerClazz = jvm.findClass("java/awt/Container") containerAddMethod = jvm.getMethod(containerClazz, "add", "(Ljava/awt/Component;)Ljava/awt/Component;") # 生成 window = jvm.newObject(clazz, constructor, ()) # Btn btn = jvm.newObject(btnClazz, btnConstructor, ("Test Button",)) container = jvm.callObjectMethod(window, containerMethod, ()) jvm.callObjectMethod(container, containerAddMethod, (btn,)) # Window jvm.callVoidMethod(window, titleMethod, ("Hello!",)) # 効果なし jvm.callVoidMethod(window, closeOperationMethod, (2,)) # 謎。(2)だと落ちる jvm.callVoidMethod(window, sizeMethod, (320, 240)) jvm.callVoidMethod(window, visibleMethod, ())
を実行すると、こうなる。
メモリリークとかはしている可能性大。あとエラー処理はすっ飛ばしたのでJNI呼び出しがおかしくなるとほいほい強制終了する。そんなんでもよければSkyDriveに置いたので試したい方はドゾ。
pyjvm - Python to Java JNI Extension ver0.1