Greetings to the mighty IronRuby experts from a humble developer!
I am testing the latest CVS snapshot (v. 73, downloaded an hour ago) of
IronRuby.
We are evaluating IronRuby for possible usage in WPF project.
First, I want to test a simple case of defining a method in Ruby and
calling the method later from C#.
Below I copy a test program that tries this in two ways (methods
AccessMethod1 and AccessMethod2).
Both attempts fail with exceptions that are written as comments in the
code.
I understand that the DLR and IronRuby are in a flux at the moment but I
still suppose there must be some working way to perform such trivial
interop task…?
Thanks in advance!
Robert B.
Software architect
Napa Ltd
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Ruby.Runtime;
using Ruby.Builtins;
namespace IronRubyTests
{
class Program
{
private IScriptEnvironment _scriptRuntime;
public IScriptEnvironment ScriptRuntime { get { return
this._scriptRuntime; } }
public IScriptEngine RubyEngine { get { return
ScriptRuntime.GetEngine(typeof(RubyContext)); } }
public ObjectOperations Operations { get { return
RubyEngine.Operations; } }
public RubyExecutionContext ExecutionContext { get { return
Ruby.IronRuby.GetExecutionContext(RubyEngine); } }
public IAttributesCollection GlobalItems { get { return
ExecutionContext.GlobalScope.Dict; } }
delegate void TestDelegate();
static void Main(string[] args)
{
new Program().RunAllTests();
}
public Program()
{
this._scriptRuntime = Ruby.IronRuby.CreateRuntime();
}
public void RunAllTests()
{
List<TestDelegate> tests = new List<TestDelegate> {
new TestDelegate(SimpleTests), new
TestDelegate(AccessMethod1), new TestDelegate(AccessMethod2)
};
foreach (TestDelegate test in tests)
{
Console.WriteLine("================== EXECUTING: {0}
====================", test.Method.Name);
try { test(); }
catch (Exception ex) { Console.WriteLine(ex); }
}
}
public IScriptScope ExecuteString(string code)
{
return ScriptRuntime.ExecuteSourceUnit(
RubyEngine.CreateScriptSourceFromString(code));
}
public void SetGlobalVar(string varName, object value)
{
ExecutionContext.GlobalVariables[SymbolTable.StringToId(varName)] =
value;
}
public object GetGlobalVar(string varName)
{
return
ExecutionContext.GlobalVariables[SymbolTable.StringToId(varName)];
}
public object GetGlobalConst(string name)
{
return
GlobalItems.SymbolAttributes[SymbolTable.StringToId(name)];
}
public void SimpleTests()
{
ExecuteString("puts 'RUBY SAYS HELLO'"); // OK
SetGlobalVar("x", 666); // OK
ExecuteString("$y=555"); // OK
ExecuteString("puts \"ruby: $x = #{$x}\""); // OK
}
public void AccessMethod1()
{
// Following fails with System.MissingMethodException:
undefined local variable or method ‘method’ for main:Object
ExecuteString(@"
def sayHello
puts ‘Hello from method!’
end
$m = method(:sayHello)
");
// Get the method object:
object m = GetGlobalVar("m");
// Here call the method, etc.
}
public void AccessMethod2()
{
ExecuteString(@"
module MyMethods
def sayHello
puts 'Hello from method!'
end
end
");
RubyModule myModule = (RubyModule)
GetGlobalConst(“MyMethods”); // OK
object sayHello = Operations.GetMember(myModule,
“sayHello”); // Fails at Assertion at
ActionBinber.UpdateSiteAndExecute()
// Here call the method, etc.
}
} // class
} // namespace