2004-11-27(Sat) 国電パンチ上り下り
■[.NET][Java][Code].NETとJavaの相互運用
IKVM.NETをご存知でしょうか? 日記でも紹介したことがありますが、.NETランタイム上で動作するJavaVMです。以前見たときは、.NET上でJavaを動かしても何が嬉しいのかよく分かってませんでしたが、調べてみたところ結構面白いことが出来ることが分かりました。
※注意
IKVM.NETをダウンロード後、binディレクトリにPathを通し、また、開発ディレクトリに
- IKVM.Runtime.dll
- IKVM.GNU.Classpath.dll
これら2つのアセンブリをコピーしていることを前提に話を進めます。
・シナリオ1
あなたは.NETプログラマです。.NETに大変満足していますが、Javaの方が歴史があるため、多数の魅力的なライブラリがあることを羨ましく思っています。今日も、こんな魅力的なライブラリを見つけてしまい、欲しくてたまりません。
import java.io.*;
public class FindFile {
public static void find(String dir) {
findSub(new File(dir));
}
private static void findSub(File dir) {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; ++i) {
if (files[i].isDirectory())
findSub(files[i]);
else
System.out.println(files[i].getName());
}
}
}
こんなもん、いらんとか言わないで。(^^; これをC#から呼び出してみましょう。上記ソースはコンパイルされ、FindFild.classになっているとします。
> ikvmc -target:library -reference:IKVM.GNU.Classpath.dll FileFind.class
このコマンドを実行するとjava bytecodeがcilへ変換されFileFind.dllが生成されます。FileFind.dllを呼び出すC#のコードを書きます。
public class Foo {
public static void Main(string[] args) {
if (args.Length > 0) {
FindFile.find(args[0]);
}
}
}
これを、Foo.csとして保存してコンパイルします。
> mcs /r:FindFile.dll,IKVM.GNU.Classpath.dll Foo.cs
これで、Foo.exeが完成です。ikvmcで変換したアセンブリをコンパイルするにはIKVM.GNU.Classpath.dllが必要になります。ちなみに、実行にはIKVM.Runtime.dllも必要なので注意です。で、
> Foo.exe c:\windows
とか実行すると、ディレクトリに存在するファイルが列挙されます。このように、.NET側からJavaを呼び出すことに成功しました。
・シナリオ2
Javaプログラマさんは面白くありません。.NET側から一方的にライブラリを利用されるだけです、腹いせに.NETライブラリを無駄に呼んでやろうとか黒い情念を燃やしています。で、yaneSDK4Csとかいうマイナーなライブラリに何故か目をつけました。どうやら、Javaから.NETを呼び出すには、ikvmstub.exeを使えば良いらしいです。
> ikvmstub mscorlib.dll
mscorlib.jarが生成され、.NETのコアライブラリは呼び出し放題です。
> ikvmstub IKVM.GNU.Classpath.dll
として、IKVM.GNU.Classpath.jarを作っておくと、.NET特有のboxing/unboxingのためのラッパークラスが使えます。準備が整ったので、いよいよyaneSDK4CS.dllを変換します。
> ikvmstub yaneSDK4CS.dll
では、変換したライブラリを呼び出してみます。
import ikvm.lang.*;
import cli.y4cs.sdl.*;
import cli.y4cs.aux.*;
import cli.y4cs.math.*;
import cli.y4cs.timer.*;
import cli.y4cs.draw.*;
public class Game {
public static void main(String[] args) {
Screen screen = new Screen();
screen.beginScreenTest();
screen.setVideoMode(640, 480, 0);
screen.endScreenTest();
Surface bg = new Surface();
Surface sp = new Surface();
bg.load("bg.bmp");
sp.load("sp.bmp");
Color4ub key = new Color4ub(
CIL.box_ubyte((byte)0),
CIL.box_ubyte((byte)0),
CIL.box_ubyte((byte)255),
CIL.box_ubyte((byte)192) );
bg.blt(sp, 0, 0, key);
Texture tx = new Texture();
tx.setSurface(bg);
FpsTimer fpstimer = new FpsTimer();
fpstimer.setFps(60);
while (GameFrame.pollEvent() == 0) {
screen.clear();
screen.blt(tx, 0, 0);
screen.update();
fpstimer.waitFrame();
}
}
}
ファイル名をGame.javaとして保存します。見てのとおり、変換したライブラリのパッケージはcli."C#での名前空間名"となります。では、こいつをコンパイルしましょう。
> javac -classpath mscorlib.jar;yaneSDK4Cs.jar;IKVM.GNU.Classpath.jar Game.java
これで、Game.classが出来ました。これで完成かと思いきや、実はこのまんま、JavaVMで実行することが出来ないのです。最初の例のように.NETアセンブリへ変換しなければなりません。
> ikvmc -reference:yaneSDK4Cs.dll:IKVM.GNU.Classpath.dll -target:exe Game.class
Javaプログラマとしては騙された気がしますが、一応、Javaでソースは書けたと無理矢理納得することに。(^^;
というわけで、.NET⇔Javaが出来ました。.NET←JavaがそのまんまJavaVMで実行できないのが残念ですけど、これは結構面白いんじゃないかと思います。