レイトバインディング
自前のC/C++ベースのWindowsソフトをJScriptで拡張可能にしたい,という要請に対して,COMベースのJScriptエンジンを利用する方法がある。それについては「C++で作ったアプリケーションとJScriptの連携」という記事に簡単な説明があるけれども,これを読んで,COMの鬱陶しさに萎えたのは自分だけではないはず。
どのみちWindows依存になってしまうのであれば,JScriptじゃなくて,JScript.NETを使ったらどうだろう・・・と思って調べてみた。.NET Framework を利用すると,驚くほどこれが簡単に実現できる。
やりたいことを,もう少し技術用語で言うと
ということになる。
コードを動的にビルドするには,System.CodeDom.Compiler および Microsoft.JScript.JScriptCodeProvider の実装を使えばよい。JScript.NET って,実のところよく知らないので,今回は,単純に Microsoft.CSharp.CSharpCodeProvider を使ってみた。
レイトバインディングを行うには System.Reflection 以下のクラスを使い,System.Activator 使って,動的に読み込んだクラスのオブジェクト作成する。
using System; using System.Reflection; using System.CodeDom.Compiler; using Microsoft.CSharp; namespace csharp_sandbox { class Program { static void Main(string[] args) { string[] input = { @"C:\Temp\hoge.cs" }; string output = @"C:\Temp\hoge.dll"; CompilerParameters parameters = new CompilerParameters(); parameters.GenerateExecutable = false; parameters.OutputAssembly = output; CompilerResults results = (new CSharpCodeProvider()).CompileAssemblyFromFile(parameters, input); if (results.Errors.Count > 0) { foreach (CompilerError error in results.Errors) { Console.WriteLine(error.ErrorText + " at line " + error.Line); } } else { Assembly a = Assembly.LoadFile(output); Type myType = a.GetType("Hoge"); object hoge = Activator.CreateInstance(myType); Console.WriteLine("Created {0}!!", hoge); MethodInfo method = myType.GetMethod("Invoke"); object[] fargs = { "HoiHoi" }; Console.WriteLine(fargs[0]); method.Invoke(hoge, fargs); Console.WriteLine(fargs[0]); } } } }
C:\Temp\hoge.cs は以下のような感じ
class Hoge { public Hoge() {} public void Invoke(ref string importantData) { System.Console.WriteLine("I processed {0}", importantData); importantData = "HoeHoe"; } }
出力結果は以下のようになる。
Created Hoge!! HoiHoi I processed HoiHoi HoeHoe
これだけだとありがたみがないけれど,自前のアプリケーションで HoiHoi だったデータが,動的に読み込んだプログラムファイル(スクリプトだと思いねぇ)を実行して HoeHoe に書き換えられていることに注目。たぶん CodeDom を色々いじると,グローバルオブジェクトの追加とか,もう少し fancy な書き方ができるようになるだろう。
今あるC++のアプリケーションをC++/CLIで.NET化して,この手法を用いてスクリプト的に拡張可能にする計画。お客さんの運用方法によって微調整が必要な処理の部分とか,よしんばバグフィックスとか,開発環境がないところでも,即座にパッチ書いて適用できたらかっこいい(かも)。