C#の JScriptCodeProvider で JScript.NET と仲良くする

C# からJScriptを呼び出すのは楽しい。

何ができるかというと、JScript のソースコードを C# 側で実行時にコンパイルできる。コンパイル後のメソッドを C# から呼び出せたりする。逆に、JScript 側から C# 側のメソッドをコールバックすることもできる。コンパイル結果は DLL として保存もできる。

ってことで、C# や VB.NET のアプリを作ってる人は、JScriptCodeProvider を使って JScript を組み込めば、「スクリプト処理系」を手に入れられるわけだ。プラグインにするもよし、設定ファイルに使うもよし。あ、あと、ちょっと努力すれば、VBScript も組み込めるので、スーツな人も大喜び。

詳しくは 文字列の計算式の計算結果を取得する: DOBON.NET の JScriptCodeProvider を使う方法が参考になる。このページでは CompileAssemblyFromSource() メソッドを使って文字列からコンパイルする方法を紹介しているが、JSDokan では CompileAssemblyFromFile() を使ってファイルからコンパイルしている。この方法が気になる人は、JSDokanProgram.cs を見て欲しい。

ここからは、DOBON.NET のページに書いていない外堀をざっくりメモしておく。

JScript.NET

JScript.NET は ECMAScript 4 を先取りしまくっていて、型付けやクラスをサポートしている。書き方は ActionScript 3 と全く同じ。

import System;

class Hoge{
    public function doHoge(filename:String):int{
        return 0;
    }
}

型は JavaScript でよく見る型以外でも、import さえしてやれば .NET のクラスは何でも利用できる。アプリで定義したクラスも ReferencedAssemblies として渡してやれば利用できる。ボーダレス!

調べてみたら、2000年に書かれた JScript.NET のドキュメントがあって、そのころから ECMAScript 4 の仕様は固まってないのかよ、と思うとしみじみしてくる。

配列を渡すには

C# から配列を渡す方法が分からなくてちょっと苦労した。

C# で Array を作るには ArrayPrototype.constructor.CreateInstance() とやって ArrayObject を作ってあげればできたんだけど、それだと C# と JScript の間での処理コストが大きい。

そこで、JScript.NET には「型指定された配列」として、String[] のような型が用意されている。今の ECMAScript4 でいうと、Vector に該当するんだろけど、2000年当時にはそんな仕様なんてなかったのかもしれない。

ってことで、受け取る側のコードは次のようにする。

class Hoge{
    public function doHoge(hoge:String[]):int{
        // hoge を ふがほげ する
    }
}

リファレンスを渡すには

JScript にはプリミティブな値を参照渡しする方法がない。一旦、配列に格納してあげて渡すようにした。かっこ悪いけど仕方ない(のかなぁ…)。

感想

2008年になって Tamarin だとか SquirrelFish だとか、JavaScript をバイトコード化する技術が脚光を浴びだしてきたけど、2000年に同じようなものを MS が開発していたというのが興味深い。

今回、久々に JScript.NET と戯れたのだけど、相変わらず MSDN のドキュメントがあっさりしていて困る。それでも、C# 1.1 のときの IVsaEngine に比べて、C# 2.0 ではだいぶだいぶ直感的になっていた。少なくとも C#1.1 時代よりかは…。

さぁ、みんな JScript.NET で遊ぼうZE!

 

関連エントリ: