概述
LuaInterface 源码下载:https://github.com/LuaDist/luainterface
LuaInterface是一个CLR库,以 .dll 的形式呈现。
要想在Unity中使用Lua,必须解决C#和Lua的交互问题,或者说CLR(即windows平台为人熟知的.Net或者linux上的Mono)和Lua的交互。LuaInterface为了解决这个问题,最重要的就是做了两件事情:
- LuaInterface 允许Lua脚本实例化CLR对象并使用它,甚至创建新的CLR对象
- 允许CLR应用程序使用LuaInterface嵌入一个Lua解释器,从而你可以通过书写lua代码扩展CLR应用程序
LuaInterface 并不能直接与lua交互,或者说,直接解释lua。它需要借助lua解释器的源码(一众C语言写的代码)来帮助解释lua,而C#层需要利用平台调用技术去使用Lua解释器提供的api,从而与lua交互。所以这里C其实充当了一个中间层,lua解释器的源码被编译成了一个动态链接库,供C#层调用。最终整个LuaInterface也会编译成一个新的动态链接库,而暴露到库外的API都由C#层实现。
使用LuaInterface
LuaInterface Binary下载:http://luaforge.net/projects/luainterface/
从上面的网站中找到最新的LuaInterface压缩包,解压,得到以下两个文件:
- 一份Native库,
lua51.dll
由lua源码编译而来,它提供了lua解释器的一系列C API - 一份托管库,
LuaInterface.dll
由LuaInterface的C#代码部分编译而来,它借助lua51.dll
去解释lua源码,并向外提供真正可用的C#层API,当我们在编写C#代码时,代码需要引用的库只有LuaInterface.dll
使用visual studio新建一个C#控制台程序,为其添加上述两个 dll 引用。
然后书写如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LuaInterface;
namespace TestLuaInterface
{
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); // 实例化一个lua解释器
lua["name"] = "chentianqin"; // 创建一个lua字符串
lua["age"] = 23; // 创建一个lua数字
lua.NewTable("people"); // 创建一个lua表
lua.DoString(@"print('This is run by lua.DoString!!!')");
lua.DoString(@"print(name)");
lua.DoString(@"print(age)");
lua.DoString(@"people[1] = 'Tom';print(people[1]);");
object[] values = lua.DoString("return name, age");
string name = (string)values[0];
double age = (double)values[1];
LuaTable table = (LuaTable)lua["people"];
Console.WriteLine("\n********以下为C#层打印的东西********\n");
Console.WriteLine("name = " + name);
Console.WriteLine("age = " + age);
Console.WriteLine("table = " + table[1]);
Console.ReadLine();
}
}
}
点击运行,如果报System.IO.FileLoadException:"混合模式程序集...
的错误,请为App.config文件里面的startup添加useLegacyV2RuntimeActivationPolicy
属性。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
程序输出如下:
在上面例子中,我们做了以下几件事情:
- 实例化了一个lua解释器,帮助我们运行lua代码
- 使用解释器实例的索引器在C#层创建lua对象,包括字符串,数字和lua表
- 使用
lua.DoString()
方法执行一段lua源码,并获得它的返回(如果源码中有return语句的话)
为此,我们已经见识到了LuaInterface如何完美地运作了。当然,LuaInterface不止如此。
LuaInterface教程
正如上面所述,LuaInterface为了解决Lua和CLR的交互完成了两件事情:允许从CLR访问Lua,以及允许从Lua访问CLR。
下面来看看这两件事情具体是如何运用的。不过在此之前,我们还需要搞清楚,这两种不同语言之间的变量类型是如何映射的。
类型转化
C#类型 | Lua类型 |
---|---|
null | nil |
System.Double | numbers |
System.String | strings |
System.Boolean | booleans |
LuaTable | table |
LuaFunction | function |
LuaUserData | userdata |
从CLR访问Lua
正如上面的示例代码一样:
Lua lua = new Lua(); // 创建一个Lua解释器实例
lua["num"] = 2; // 使用索引器去创建一个lua变量
lua["str"] = "a string";
lua.NewTable("tab"); // 使用NewTable()去创建一张lua表
double num = (double)lua["num"]; // 使用索引器去访问一个lua变量
string str = (string)lua["str"];
lua.DoFile("test.lua"); // 使用DoFile()去运行一个lua脚本
object [] rets = lua.DoString("return num, str;"); // 使用DoString()去执行一段lua源码
从Lua访问CLR
最新的LuaInterface(version >= 2.0.1)内置的解释器包含了一套库,里面自带一个全局的luanet
模块。这个模块允许你加载CLR的程序集和CLR类型。
luanet.load_assembly("System.Windows.Forms") -- 使用load_assembly加载CLR程序集
luanet.load_assembly("System.Drawing")
Form=luanet.import_type("System.Windows.Forms.Form") -- 使用import_type导入CLR类型
Button=luanet.import_type("System.Windows.Forms.Button")
Point=luanet.import_type("System.Drawing.Point")
form1=Form() -- 导入之后就可以正常使用类型进行实例化和访问成员方法
button1=Button()
button2=Button()
function handleClick(sender,data)
if sender.Text=="OK" then -- 使用点句号 . 访问成员变量
sender.Text="Clicked"
else
sender.Text="OK"
end
button1.MouseUp:Remove(handler) -- 使用冒号 : 访问成员方法
print(sender:ToString())
end
button1.Text = "OK"
button1.Location=Point(10,10)
button2.Text = "Cancel"
button2.Location=Point(button1.Left, button1.Height + button1.Top + 10)
handler=button1.MouseUp:Add(handleClick)
form1.Text = "My Dialog Box"
form1.HelpButton = true
form1.MaximizeBox=false
form1.MinimizeBox=false
form1.AcceptButton = button1
form1.CancelButton = button2
form1.Controls:Add(button1)
form1.Controls:Add(button2)
form1:ShowDialog()
这是一个官方的实例。将之保存为一个lua脚本,然后在C#里使用DoFile()方法执行它,你会得到如下结果: