Jython を学ぶ(2)
前回(http://d.hatena.ne.jp/Monolithic/20080824/1219582882)の例のよくない点を訂正します。
- Python の callable オブジェクトを実行する、 Runnable を実装したクラス PyCallableRunnable を用意。いちいちクラスを作るのは Pythonic ではありませんでした。
- Runnable を AWT スレッドで実行するのに、 javax.swing.SwingUtilities#invokeLater を使っていたのを java.awt.EventQueue#invokeLater を使うように訂正。これは単に、 AWT スレッドで実行するのに Swing の API を使うのは奇妙ではないかと私が思ったというだけで、たいした違いではないでしょう。
- from ... import ... で import * するのをやめて、クラス一つ一つをインポートするように訂正。
#! jython from java.lang import Runnable from java.awt import Rectangle from java.awt import EventQueue from javax.swing import JFrame class PyCallableRunnable(Runnable): def __init__(self, pyCallable): self.pyCallable=pyCallable return def run(self): self.pyCallable() return def initializeAWT(): def windowClosing(e): window=e.getWindow() window.visible=False window.dispose() return JFrame( windowClosing=windowClosing, bounds=Rectangle(800, 600), title="Hello, world! ", visible=True ) return if __name__=="__main__": EventQueue.invokeLater(PyCallableRunnable(initializeAWT))
ソースコードの解説
このコードを test.py に保存し、そのディレクトリで以下のコマンドを実行します。
jython test.py
すると Swing のウインドウが現れるはずです。ウインドウを閉じると、しばらくしてプログラムも終了するはずです。
Python スクリプトがトップレベルとして実行されると、モジュール名( __name__)は"__main__"になります。このため、if __name__=="__main__": の中身はこのスクリプトをトップレベルで実行したときにのみ実行されます。
PyCallableRunnable クラスはコンストラクタの引数に python の関数を取り、それを run メソッドで実行する、 java.lang.Runnable インターフェースを実装したクラスです。
initializeAWT 関数は、大きさが幅 800px 、高さ 600px 、タイトルが"Hello world! "、生成時に可視状態になり、閉じると破棄される JFrame クラスのインスタンスを生成します。このとき Python の名前付き引数で Java Beans のプロパティ(bounds, title, visible)を設定しています。
windowClosing 関数はウインドウが閉じられると呼ばれ、ウインドウを不可視にした後 java.awt.Window#dispose を呼び出します。
Jython は JFrame の WindowListener を自動的に登録し、WindowListener#windowClosing が windowClosing プロパティに指定された関数を呼び出すようにしてくれています。おかげで Listener インターフェースを実装した冗長なクラスを記述する必要がありません。
java.awt.EventQueue#invokeLater メソッドは、引数に与えられた Runnable オブジェクトを AWT スレッドで実行します。AWT 関連の(そして Swing 関連の)API の多くは AWT スレッドで呼び出さなければなりません。
initializeAWT をコンストラクタの引数にとった PyCallableRunnable クラスのインスタンスを invokeLater メソッドに与えることで、AWT スレッドで initializeAWT 関数が実行されます。
ウインドウを閉じると windowClosing 関数が呼び出され、ウインドウは dispose されます。全てのトップレベルウインドウが dispose されるとAWT スレッドがシャットダウンし、他にnon-daemon スレッドが走っていなければ JVM がシャットダウンすると思います。これについてはhttp://java.sun.com/javase/ja/6/docs/ja/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdownに書いてあります。
Jython を学ぶ(1)
私が書くようなプログラムは「なんか予想外の事態になったら例外吐いて停止すればいい」ものがほとんどです。
そう考えると Scala より Jython が適切な選択ではないかと思い直しました。
#! jython from java.lang import * from java.awt import * #from java.awt.event import * from javax.swing import * class Application(Runnable): def run(self): def windowClosing(e): window=e.getWindow() window.visible=False window.dispose() #import sys #sys.exit() JFrame( windowClosing=windowClosing, bounds=Rectangle(800, 600), title="Hello, world! ", visible=True ) if __name__=="__main__": SwingUtilities.invokeLater(Application())
jython test.py
D言語のイントリンシック命令
VC のイントリンシック命令
イントリンシックとはコンパイラ組み込みの関数のことです。
Visual C++ 9.0 のイントリンシック命令は MSDN の以下の URL に載っています。
Intrinsics Available on All Architectures:
Itanium Intrinsics:
x64 Intrinsics:
_Interlocked** 擬似関数
Windows API には Interlocked*** という名前の関数群があって、それらを呼び出すことによってC言語では書けない atomic な操作、例えば他のスレッドに邪魔されずに変数をインクリメントしたりすることが必要なコードを簡単に書くことができます。_Interlocked*** という名前のイントリンシック命令は Interlocked*** 関数のイントリンシック版のようですね。
また、私は使ったことがないのですが GCC でもバージョン 4.1 以降で atomic な操作を行うためのイントリンシック命令が導入されたようです。
Built-in functions for atomic memory access
http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
gcc-4.1からatomic関係の関数がビルトインに
http://d.hatena.ne.jp/tasukuchan/20060810
atomic だとかスピンロックだとかいう話はまたいずれしたいと思います。
C 標準ライブラリの関数のイントリンシック版
memcpy だとか strcpy だとか言ったメモリ関連・文字列関連の標準関数や、数学計算関連の関数がイントリンシック命令として用意されています。
これらの関数はコンパイラ組み込みの擬似関数ですから、 CRT をリンクしなくても使うことができます。
Scala 関連 URL
The Scala Programming Language(本家)
Wikipedia の解説
http://ja.wikipedia.org/wiki/Scala
http://en.wikipedia.org/wiki/Scala_(programming_language)
Scala言語の入門書の紹介
Scala を学ぶ(1)
とりあえず Swing でウインドウを出すコードを書いてみた
Java 版(HelloWorld.java)
import java.awt.*; import java.awt.event.*; import javax.swing.*; class HelloWorld{ public static void main(String arg[]){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ final JFrame frame=new JFrame(); frame.setBounds(new Rectangle(800, 600)); frame.setTitle("Hello, world! "); frame.addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e){ frame.setVisible(true); frame.dispose(); } }); frame.setVisible(true); } }); } }
Scala 版(test.scala)
import java.awt._ import java.awt.event._ import javax.swing._ object HelloWorld{ def main(args: Array[String]){ SwingUtilities invokeLater new Runnable{ def run(){ val frame=new JFrame frame setBounds new Rectangle(800, 600) frame setTitle "Hello, world! " frame addWindowListener new WindowAdapter{ override def windowClosing(e:WindowEvent){ frame setVisible false frame dispose } } frame setVisible true } } } }
scalac test.scala
java -classpath .;
Java 版を直訳しただけであんまりいい例じゃないな
色々な JVM 実装(1)
いろんな JVM の実装と簡単な紹介を列挙してみる
Sun の HotSpot http://openjdk.java.net/groups/hotspot/
Sun の Java についてるやつ。
Java1.2 でアドオンとして搭載され、Java1.3 でデフォルトの VM となった。
というか 1.0 から 1.2 までは JIT じゃなかったらしい。そりゃ遅いだろ……
SmallTalk VM や Self VM の技術が転用されたとか聞くけどよく知らない。
HotSpot と呼ばれるのは、最適化すべき場所(HotSpot)だけ JIT コンパイルするかららしい。
C++ と アセンブリ言語で書かれている。
対応 CPU は x86, x64, SPARC。
JNode の JVM http://www.jnode.org/
JNode は最小限のアセンブリ言語と Java で書かれた OS 。
JNode は Java のネイティブコンパイラを持っているようだ。
http://www.jnode.org/node/37
この辺の仕組みがよくわからない。AOT と JIT の中間みたいな動作をするのだろうか。
JNode をちょっと使ってみて驚いたのは、結構実用的に動いたことだ。いずれこのことについては詳しく書こうと思う。