Lua Interface

lua-users home
wiki

LuaInterface is a library for integration between the Lua language and Microsoft .NET's Common Language Runtime (CLR). Lua scripts can use this to instantiate CLR objects, access properties, call methods, and even handle events with Lua functions.

Web sites:

Dependencies: .NET. Also works on the Mono runtime http://www.mono-project.com on Linux.

Note: Version 1.5.3 builds a C module DLL that can loaded in regular Lua interpreter. Version 2.0 and above are completely managed code. [4][5][6][7][2][3]

User Comments

Not mentioned in the LuaInterface documentation is how to instantiate .NET arrays. It is done simply by indexing a type reference with a number:

local a = SomeType[5]
for i = 1,a.Length do
	print(i, a[i - 1]) -- .NET arrays are zero-based.
end


[ LuaInterface-1.3.0 adds the following feature ]

When using the CLR from Lua, the ordinary method of loading types and classes can seem a little verbose:

net = require "luainterface"

net.load_assembly("System.Windows.Forms")
net.load_assembly("System.Drawing")

Form = net.import_type("System.Windows.Forms.Form")
Button = net.import_type("System.Windows.Forms.Button")
Point = net.import_type("System.Drawing.Point")

local form1 = Form()
local button1 = Button()
button1.Location = Point(10, 10)

It would be nice if syntax like this could be used:

require "net"

Form = net.System.Windows.Forms.Form
Button = net.System.Windows.Forms.Button
Point = net.System.Drawing.Point

local form1 = Form()
local button1 = Button()
button1.Location = Point(10, 10)

Optionally, the .NET types can be made to appear as toplevel names:

require "net"

System = net.System

Form = System.Windows.Forms.Form
Button = System.Windows.Forms.Button
Point = System.Drawing.Point

local form1 = Form()
local button1 = Button()
button1.Location = Point(10, 10)

It should not be necessary to make every type name toplevel:

require "net"

System = net.System

local form1 = System.Windows.Forms.Form()
local button1 = System.Windows.Forms.Button()
button1.Location = System.Drawing.Point(10, 10)

Here is the method:

-- Create a metatable for our name components
local metatable = { [".NET"] = {getmetatable=getmetatable} }

-- Load LuaInterface
local g = getfenv(0)
setfenv(0, metatable[".NET"])
local init, e1, e2 = loadlib("LuaInterfaceLoader.dll", "luaopen_luainterface")
assert(init, (e1 or '') .. (e2 or ''))
init()
setfenv(0, g)

-- Lookup a .NET identifier component.
function metatable:__index(key) -- key is e.g. "Form"
    local mt = getmetatable(self)
    local luanet = mt[".NET"]

    -- Get the fully-qualified name, e.g. "System.Windows.Forms.Form"
    local fqn = ((self[".fqn"] and self[".fqn"] .. ".") or "") .. key

    -- Try to find either a luanet function or a CLR type
    local obj = luanet[key] or luanet.import_type(fqn)

    -- If key is neither a luanet function or a CLR type, then it is simply
    -- an identifier component.
    if obj == nil then
		-- It might be an assembly, so we load it too.
        luanet.load_assembly(fqn)
        obj = { [".fqn"] = fqn }
        setmetatable(obj, mt)
    end

    -- Cache this lookup
    self[key] = obj
    return obj
end

-- A non-type has been called; e.g. foo = System.Foo()
function metatable:__call(...)
    error("No such type: " .. self[".fqn"], 2)
end

-- This is the root of the .NET namespace
net = { [".fqn"] = false }
setmetatable(net, metatable)

-- Preload the mscorlib assembly
net.load_assembly("mscorlib")

return nil

See Also


RecentChanges · preferences
edit · history
Last edited July 26, 2011 7:25 am GMT (diff)