The most exciting thing about this world is its ever changing quality.

Showing posts with label script engine. Show all posts
Showing posts with label script engine. Show all posts

Saturday, February 14, 2009

Lua in .Net

ALthough I have mentioned before that there are a few options to enable scripting in .Net projects, I was thinking write a interface library to wrap up the unmanaged C style Lua library into a CLR compliant module. It is actually pretty straightforward process. Some nice people have already written ref class LuaDLL to solve the marshalling between unmanaged functions to unmanaged APIs. Essentially, you could use LuaDLL directly within your .Net project. To simplify things, what I was looking for is to wrap Lua into an object oriented way, as some OO nuts like to brand it. What LuaDLL does not do is to offer an easy way allowing Lua script accessing CLR type objects.

Without too much efforts, to pack all the fancy Lua interpreter, table, function and user data into classes, and some counter-effective strings to be executed by Lua runtime to set the meta data. Here we are, a nice interface class - LuaInterface, which defeats my original plan to be the first integrator ... And, it was done long time before my consciousness.

Anyway, to use this interface could not be easier. You can access CLR objects from Lua scripts which essentially will be string format to be executable by Lua runtime and manipulated from CLR objects vice versa. What I like about this is to hook up event handler and use delegate just as easily. On the contrary, I could not locate any good summary on this subject thus I listed in this post.

  • Define delegate in C# to use Lua functions:

// Lua interpreter
private Lua lua;
// function pointers to functions in Lua
public delegate double PlusDelegate(double a, double b);

public Script()
{
lua = new Lua();
// define variables in Lua
lua["num"] = 2;
lua["str"] = "a string";
// define functions in Lua

lua.DoString(@"
function plus(x, y)
return x + y
end
");

// use functions defined in Lua
PlusDelegate plus = lua.GetFunction(typeof(PlusDelegate), "plus") as PlusDelegate;

if (IsDefinedInLua(add))
{
double res = plus(10, 2);
rtbOutput.Text = (String.Format("result: {0}", res));
}
}

private bool IsDefinedInLua(Delegate delegateOfFunction)
{
if (delegateOfFunction.Target is LuaDelegate)
return (delegateOfFunction.Target as LuaDelegate).function != null;

return false;
}

  • Define 'delegate' in Lua to use C# functions:

public void CallCSharp(string s)
{
rtbOutput.Text += ;
}
lua.RegisterFunction("callCSharp", this, this.GetType().GetMethod("CallCSharp"));

Just to be aware that the function has to be public to be registered into Lua. You could also use Lua function by instance as:

// use a Lua function by instance
LuaFunction luaFunction = lua.GetFunction("minus");
double ret = (double) luaFunction.Call(10,2).GetValue(0);


  • Implement event defined in C# from Lua, a.k.a bind events to scripted handlers.

public delegate void RaiseAttentionEventHandler(object sender, EventArgs e);
public event RaiseAttentionEventHandler RaiseAttention;

lua.DoString(@"
function clickMe (sender)
sender.Text = 'It worked'
end
");

lua.DoString(@"
newPanel = ScriptPanel('aNewPanel')
newPanel.RaiseAttention:Add(clickMe)
");
if (this.RaiseAttention != null)
RaiseAttention(sender, null);

  • Implement event defined in Lua from C# is a little twisted logic. I could not think of a good use case right now but for the sake of completeness sake, I did a little trial and error. Before moving on, you might want to refresh a little about the event support in Lua here. Another good event module implementation using C library could be found here. The easiest way I found is to register C# functions into Lua as global function and use them to handle the events in Lua. 

private void btLua_Click(object sender, EventArgs e)
{
// Implement event defined in Lua from C# and trigger it in Lua
LuaEventHandler handler = new LuaEventHandler();
lua.RegisterFunction("eventInLua", this, this.GetType().GetMethod("EventInLua"));
handler.handler = lua.GetFunction("eventInLua");
handler.handleEvent(sender, e);
}

public void EventInLua(object sender, EventArgs e)
{
rtbOutput.Text = ("Trigger from Lua ");
return;
}

Monday, November 17, 2008

Script engine in .Net

Embedded script engine in applications which require significant level of customisation is a very attractive idea. More than that, the script based component actually makes the component level deployment possible, a different implementation to plug-in structure. One thing to look out for is surely performance.

  1. CS-Script is claimed to support on .NET1.1/2.0/3.0/3.5 versions of CLR implementation with limited support on Mono. It effectively creates the support for CLR code compilation. You have accesses to all the libraries supplied from .Net. With the use of configuration file for scripts, you could really extend your application functionalities. In addition, you can take advantage of other CLR compilers (by instantiating System.CodeDom.Compiler.ICodeCompiler interface) and Config console. Referring to namespace would be able to access your own object model. One good thing is that with CS-Script, you can compile any scripts into standalone executable.
  2. Prior to .Net 3.5, namespace Microsoft.Vsa offers the built-in scripting capability. Vsa really is a .Net version of VBA. You create your own instance of engines from Microsoft.Vsa.IVsaSite interface, from which you can implement your engine to accommodate VB script, Java script and C# script engine. An easy tutorial can be found at here. You could expose your object model within your application to be reused from scripts later on as well.
  3. Good old days - Microsoft Script Control used in managed project. Again, you can expose your own class model via this. You would need to instantiate an instance from MSScriptControl.ScriptControlClass and then select the script engine for either VBScript of JavaScript (of course MS version of JS). This article has introduce an interesting way of scripting asynchronous call.
  4. There are a few other script engines projects available as well. Google will take you there I am sure. I will not go on here.
Be aware the difference with Windows Script Interface. WSH enables Windows OS to run scripts in a way extending batch file. By default Windows will interpret JS and VBS files, with WSF you should be able to have a sense of language independent OS scripting. Although WSI has been deprecated since .Net 3.5. You could even create script COM objects using Window Script Component. However, Windows Script allows you to script capability at OS level. If you imagine Windows as AN application (well, not the best one shall we say), and Windows Script provides a way to Script this application.