LuaInterface is a library for integration between the Lua language and Microsoft .NET platform's Common Language Runtime (CLR). Lua scripts can use it to instantiate CLR objects, access properties, call methods, and even handle events with Lua functions.
Originally written by Fabio Mascarenhas, and currently maintained by Craig Presti at here
This corresponds to the latest version 2.0.3, backported to use P/Invoke against standard Lua 5.1 shared libraries. It provides a working version of LuaInterface buildable on Mono.
On Debian/Ubuntu, you will need the liblua5.1-dev and mono-devel packages.
To build, go into the src directory, and:
$ ./configure
This requires a Lua installation to run, but no other dependencies. It will look
for the Lua headers in the usual places, /usr/include and /usr/include/lua51,
if your Lua directory is somewhere else altogether set LUA_INCLUDE:
$ ./configure LUA_INCLUDE=/home/you/lua-5.1.5/src DEFINES=lua
DEFINES here is overriding the default on Linux, which is to assume
the Lua shared library looks like liblua5.1.so rather than lua51.so.
Configuration of LuaInterface is controlled by two C# preprocessor defines,
__Windows__ and __liblua__. The first makes the shared library extension '.dll',
and the second makes the Lua shared library name 'liblua5.1' rather than 'lua51'.
The latter is the default for Linux, at least for Debian/Ubuntu. Look at
src/LuaDLL.cs to see how these are used, and how to modify for your
configuration.
(Currently, this project builds against Lua 5.1 or LuaJIT.)
$ make
$ ./
Last step assumes you have a ~/bin directory, but you can install globally with
$ sudo ./install /usr/local/bin
(You can also install globally with e.g sudo ./install /usr/local/bin)
It will generate a wrapper script called luai looking like this:
#!/bin/sh
LUAI=/home/azisa/lua/MonoLuaInterface/bin
export LD_LIBRARY_PATH=$LUAI
export LUA_PATH=";;$LUAI/lua/?.lua"
/usr/bin/mono $LUAI/luai.exe $*
We have to locally mess with LD_LIBRARY_PATH (or DYLD_LIBRARY_PATH on
OS X) because LuaInterface will need to find both the Lua shared library and the
stub library luanet.so.
The samples directory contains the original samples, plus some extended ones from the Lua for Windows project.
Here is the proverbial 'Hello World':
-- hello.lualuanet.load_assembly"System"localConsole=luanet.import_type"System.Console"localMath=luanet.import_type"System.Math"Console.WriteLine("sqrt(2) is {0}",Math.Sqrt(2))Using the CLRPackage utilities, it is even simpler, since individual classes will be
loaded as needed:
-- hello2.luarequire'CLRPackage'import"System"Console.WriteLine("sqrt(2) is {0}",Math.Sqrt(2))If you want an interactive prompt, then there is a Lua interpreter in Lua, called
lua.lua, in the samples directory:
samples$ luai lua.lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
lua.lua (c) David Manura, 2008-08
> require 'CLRPackage'
> Console.WriteLine("hello from Mono") -- 'System' is already loaded...
hello from Mono
>
It is straightforward to write GTK# applications in Lua - note that here the
import call is passed the package name and the namespace, in cases where
they are not the same:
-- hello-gtk.luarequire'CLRPackage'import ('gtk-sharp','Gtk')
Application.Init()
localwin=Window("Hello from GTK#")
win.DeleteEvent:Add(function()
Application.Quit()
end)
win:Resize(300,300)
locallabel=Label()
label.Text="Hello World!"win:Add(label)
win:ShowAll()
Application.Run()
This automatically creates globals, which is the only way that Lua can mimick the usual C# scope resolution rules. For larger programs, this is probably not a good idea, and so there's a way of explicitly creating namespaces:
-- hello-gtk2.luarequire'CLRPackage'luanet.load_assembly'gtk-sharp'localgtk=luanet.namespace'Gtk'gtk.Application.Init()
localwin=gtk.Window("Hello from GTK#")
win.DeleteEvent:Add(function()
gtk.Application.Quit()
end)
win:Resize(300,300)
locallabel=gtk.Label()
label.Text="Hello World!"win:Add(label)
win:ShowAll()
gtk.Application.Run()
LuaInterface is usually used by CLR applications which need a scripting language.
An example of the high-level interface with Lua is tests/CallLua.cs; this directory
also has the original C# tests. (These all pass, except for passing a managed function
to string.gsub, which is a Lua limitation.)
A basic C# program is here; it evaluates Lua expressions:
usingSystem;usingLuaInterface;publicclassTestLua{publicstaticvoidMain(string[]args){if(args.Length==0){Console.WriteLine("provide a Lua expression!");}else{LuaL=newLua();// will open all the standard Lua librariestry{object[]results=L.DoString("return "+args[0]);Console.WriteLine("answer is {0}",results[0]);}catch(Exceptione){Console.WriteLine("error: {0}",e.Message);}L.Close();}}}It must be compiled with a reference to LuaInterface.dll, and both luanet.so and liblua5.1.so must be accessible on the library path.
These are contained in the global table luanet:
''luanet.load_assembly''
Loads a CLR assembly; will throw an error if not found.
''luanet.import_type''
Bring in a class using the fully qualified name, e.g.
C = luanet.import_type 'System.Console'. The assembly must have been previously
loaded.
''luanet.get_object_member''
This is given an object, and an index (string or integer). It can be used to look up a property value, and will return nil + error message if the property does not exist. (Looking up fields and indices directly will fail with an error).
''luanet.make_object''
This takes a table and a CLR class name and allows you to override any virtual methods of that class.
For instance, given this C# class:
publicclassCSharp{publicvirtualstringMyMethod(strings){returns.ToUpper();}publicstaticstringUseMe(CSharpobj,stringval){returnobj.MyMethod(val);}}then the following Lua code creates a proxy object where MyMethod is overriden:
luanet.load_assembly'CallLua' -- load the assembly containing CSharplocalCSharp=luanet.import_type'CSharp'localT= {}
functionT:MyMethod(s)
returns:lower()
endluanet.make_object(T,'CSharp')
print(CSharp.UseMe(T,'CoOl'))There is a corresponding luanet.free_object for explicit disposal.
(See tests/CallLua.cs)
In addition, this version of LuaInterface defines two extra functions
''luanet.ctype''
This is the equivalent of typeof in C#; given a class proxy object, return the
actual CLR type.
samples $ luailua.luaLua5.1.4 Copyright (C) 1994-2008Lua.org, PUC-Riolua.lua (c) DavidManura, 2008-08>=StringProxyType(System.String): 54267293>ctype=luanet.ctype>=ctype(String)
System.String: 2033388324''luanet.enum''
This has two forms. The first casts an integer into an enum type:
>enum=luanet.enum>import'System.Reflection'>=BindingFlags.StaticStatic: 8>=enum(BindingFlags,8)
Static: 8The second form parses a string representation for an enumeration type. This is useful for enum flags:
>=enum(BindingFlags,'Static,Public')
Static, Public: 24It's now possible to use CLR reflection in a non-clumsy way; see tests/ctype.lua
for an example of using the Lua API directly from Lua itself, by importing all
static methods of the LuaDLL class.
This Lua module provides some very useful shortcuts. We have already seen import,
which brings classes into the global Lua table. This is not appropriate for larger
applications, so there is luanet.namespace. Note that its argument may be a table:
localgtk,gdk=luanet.namespace {'Gtk','Gdk'}(You do have to explicitly load the assemblies before using this)
''luanet.make_array''
This is a convenience function for creating CLR arrays; it is passed a class (the proxy, not the type) and a table of values.
Note that the Lua expression Class[10] already makes us a Class[] array!
Bear in mind that CLR arrays index from zero, and throw a range error if the index is out of bounds.
''luanet.each''
This constructs a Lua iterator from an IEnumerable interface:
>dd=make_array(Double,{1,2,10})
>forxineach(dd) doprint(x) end1210>import'System.Collections'>al=ArrayList()
>al:Add(10)
>al:Add('hello')
>foroineach(al) doprint(o) end10hello>ht=Hashtable()
>ht.one=1>ht.two=2>forpineach(ht) doprint(p.Key,p.value) endone1two2