DLR メモ書き
DLRに関するメモ書き残しとく。
ちなみに、DLR 0.9(Dec 11 2008 のバイナリ)の話。
下準備
C# からスクリプトコード呼び出し
- 基本的な流れは
- ScriptRuntime runtime = ScriptRuntime.CreateFromConfiguration();
- ScriptEngine engine = runtime.GetEngine("拡張子");
- CompiledCode code = engine.CreateScriptSourceFromFile(path).Compile();
- code.Execute();
- C# → スクリプトに値渡して、計算結果を C# 側で受け取るのがいまいちやりにくい
- 1.0 になったら少しはましになるのかなぁ
static void ExcuteSum() { var x = new[] { 1, 2, 3, 4, 5 }; var q = x.Select(p => p * p); ExcuteSum(Path.Combine(basePath, "sum.py"), q); ExcuteSum(Path.Combine(basePath, "sum.rb"), q); } static readonly ScriptRuntime runtime = ScriptRuntime.CreateFromConfiguration(); static CompiledCode GetCompiledCode(string path) { var ext = System.IO.Path.GetExtension(path).Replace(".", ""); var engine = runtime.GetEngine(ext); return engine.CreateScriptSourceFromFile(path).Compile(); } static void ExcuteSum(string path, IEnumerable<int> list) { var compiled = GetCompiledCode(path); var scope = runtime.CreateScope(); scope.SetVariable("arg", list); // ↑ 引数を渡す機能とかないみたい?なので、変数として値をセット。 object result = compiled.Execute(scope); // ↑ IronPython だとこれで戻り値を返せない。 if (result == null) { result = scope.GetVariable("result"); // ↑ 逆に、IronRuby だと、result 変数が scope に残らない。 } Console.Write("{0}, {1}\n", result, result.GetType().Name); // ↑ 55, Int32 って表示されるはず }
sum.py の中身。
sum = 0 for x in arg : sum += x result = sum # sum # IronPython では、これで戻り値返せない # sys.exit(sum) # これで値を返せるけども、エラーコードになる。非0だと異常終了扱いされる
sum.rb の中身。
sum = 0 arg.each do |x| sum += x end # result = sum # IronRuby だと、スクリプト実行後、result 変数がスコープに残らない sum # 戻り値
ユーザー定義型の受け渡し
- C# で書いた型を IronPython, IronRuby に渡すのは何の問題もない
- IronPython で書いた型を IronRuby に渡してもプロパティアクセスできない。逆もまたしかり
- ドキュメント読んでる感じ、正式版までにはできるようになりそうな雰囲気だけど
例:
まず、以下の Python コードを実行。
x = 3 class Point: def getValue(self): return self.__v def setValue(self, val): self.__v = val y = Point() y.Value = 5 z = y.Value * y.Value
次に、以下の Ruby コード。
print x * x print z # ↑この2行はちゃんと実行できる p y # ↑表示結果は #<IronPython::Runtime::Types::OldInstance:0x000005c> #print y.Value # ↑この行、「undefined method `Value'」って怒られる class Point attr_accessor :x, :y def initialize(x, y) @x = x; @y = y end end $w = Point.new(3, 4) v = $w.x * $w.y $v = $w.x * $w.y $w
IronRuby のスクリプトを実行しても、変数がスコープに残らないので、次、Python に値を渡すために C# 側で以下のような作業をする。
var result = c2.Execute(scope); // 前述の Ruby コードの実行 scope.SetVariable("w", result); c3.Execute(scope); // 後述する Python コードの実行
で、最後に以下の Python コードを実行。
#print v # ↑この行、「'v' is not defined」って怒られる print w.GetType().Name # ↑表示結果は IronRuby.Builtins.RubyObject result = w.GetType() #result = w.x * x.y # ↑この行、「'RubyObject' object has no attribute 'x'」って怒られる