Tolua框架学习之一——LuaInterface

          文章参考来源:https://blog.csdn.net/heyuchang666/article/details/50722658

           LuaInterface.Lua类是CLR访问Lua解释器的主要接口,一个LuaInterface.Lua类对象就代表了一个Lua解释器(或Lua执行环境),Lua解释器可以同时存在多个,并且它们之间是完全相互独立的。简单来说,LuaInterface就是用于Lua和C#交互的工具。

      LuaInterface的下载地址:http://luaforge.net/projects/luainterface/。下载后解压即可获取两个dll文件:luanet.dll和luainterface.dll。

          我使用的是VS2017新建的工程。加入两个dll文件的引用后,引用luainterface命名空间即可。此时如果实例化一个解释器实例,运行时会报错,如下:

如下:

这个问题的解决可以参见:https://blog.csdn.net/bbnbf/article/details/7010551

      解决问题后,开始学习之路。

      lua和C#的交互无非就是lua调用C#的字段,方法。C#调用lua的方法,执行lua脚本。

  • C#执行lua脚本(创建变量,执行方法等)

    可以使用索引操作符[]来创建变量,NewTable()用于创建一个空表格,要修改数据,需要用到lua对表的操作。例如:

class Program
{
        static void Main(string[] args)
        {
            // 创建一个lua解释器。每个lua实例都是相互独立的
            Lua lua = new Lua();

            // lua的索引操作[]可以创建,访问,修改global域,括号里面是变量名
            // 创建global域num和str两个变量
            lua["num"] = 2;
            lua["str"] = "this is a string";

            // 创建空的table
            lua.NewTable("tab");
        }
}

 DoString()方法可以执行一段lua代码,参数是一段string类型的lua代码片段。

 class Program
    {
        static void Main(string[] args)
        {
            // 创建一个lua解释器。每个lua实例都是相互独立的
            Lua lua = new Lua();

            // lua的索引操作[]可以创建,访问,修改global域,括号里面是变量名
            // 创建global域num和str两个变量
            lua["num"] = 2;
            lua["str"] = "this is a string";

            // 创建空的table
            lua.NewTable("tab");


            // 执行lua脚本,这两个方法都会返回object[] 记录脚本的执行结果
            lua.DoString("num = 100, print('i an a string')");

            lua.DoString("local a = {1,2,3}  " +
                "for k,v in pairs(a) do  " +
                "print(k,v) " +
                "end");
        }
}

执行结果如下,可以看出,我们正确遍历了table。只不过,写起来有点怪怪的。

执行结果如下:

Dostring()方法会返回一个object[]类型的数组。可以获取lua中执行结果的返回。如下所示:

如下所示:

会发现,没有获取到表a的值。这是因为DoString()方法是执行的lua代码片段。这里的a和上一段的表a不是同一个变量。如果改成“return a = 10”,那么就会打印出结果10。

       DoFile()方法用于执行lua脚本,参数是lua脚本的路径,如下:

路径。如下:

       LuaIntrface自动对应Lua和CLR中的一些基础类型
  [nil, null]
  [string, System.String]
  [number, System.Double]
  [boolean, System.Boolean]
  [table, LuaInterface.LuaTable]
  [function, LuaInterface.LuaFunction]
以上对应关系反之亦然。如下图所示:

亦然。如下图所示:

  •  Lua执行C#脚本

     RegisterFunction方法用来将CLR函数注册进Lua解释器,供Lua代码调用。该方法接收三个参数:string path, object target, MethodBase function。path指注册进lua的函数在lua中的名字, target指方法的对象实例,function指方法。如下,我们新建一个类,里面写一些打印输出方法:

里面写一些打印输出方法:

注册进lua后,用DoString方法执行:

用DoString方法执行:

可以看到,方法被正确执行了。另外,我们看到,静态方法,第二个参数是不用传递的(null)。这里我们使用GetMethod()来获取类中的方法。RegisterFunction的返回值类型是LuaFunction类型。接收的是lua中的函数。如下,我们在LuaCallCSharpTest类中新增一个方法:

类中新增一个方法:

LuaFunction类型对应的是lua种的function。使用Call方法,就可以执行lua中的该方法。

  • CLR from Lua

       这里我们在外部编写lua脚本,然后在C#中调用。Luainterface主要提供了下面几个方法:    

       luanet.load_assembly函数:加载CLR程序集;

  luanet.import_type函数:加载程序集中的类型;

  luanet.get_constructor_bysig函数:显示获取某个特定的构造函数;

我们可以通过这几个方法。加载C#代码到lua中去。加载指定程序集下面的指定类。

C#测试代码如下,我们写了几个不同的构造函数,然后尝试在lua中进行匹配。

然后尝试在lua中进行匹配。 

 编写lua脚本,脚本我是放在项目工程目录下的,

脚本我是放在项目工程目录下的,

也可以将luanet.dll 拷贝到工程 DeBug 输出目录中,然后需要将写好的Lua文件拖到项目中,并且修改属性为 :如果较新则复制 / 始终复制。否则会出现找不到文件的 报错信息。这样也同样不需要require了。

lua脚本如下:

lua脚本如下:

程序集的名字可以在项目中进行设置,在菜单的项目->XXX属性下面就可以设置了。import_type中就是命名空间的名字了。

        从上面的构造函数的匹配可以看出,LuaInterface匹配构造函数的规律:

  LuaInterface匹配第一个能够匹配的构造函数,在这个过程中,numerical string(数字字符串)会自动匹配number,而number可以自动匹配string,所以CSharpFromLua(3)匹配到了参数为string的构造函数。

  如果一定要手动匹配某个构造函数,则可以使用luanet.get_constructor_bysic函数。

  • 访问C#对象和字段

       Lua代码中,访问CLR类型对象的字段的方式和访问table的键索引一样,比如button1.Text、button["Text"];

  Lua代码中,访问CLR类型对象的函数的方式和调用table的函数一样,比如form:ShowDialog()。

C#测试代码和lua代码如下:

C#测试代码如下:

C#测试代码和lua代码如下

使用DoFile()执行lua文件,输出结果如下:

输出结果如下:

我们已经通过构造函数实例化了该类,所以只要直接调用方法即可。这里使用冒号操作符来调用类的方法,使用[]来访问类的字段,这一点和访问table是一样的。冒号和点号的使用区别可以在网上查到。

       其他还有一些特殊情况:

       当有重载方法时,匹配的规则就可上面介绍的一样。可以使用luanet.get_method_bysig方法来匹配指定的方法。如下图:

如下图:

数字字符串类型的参数,会自动匹配int。而普通的字符串则会自动匹配string参数。

       当函数有out或ref参数时,out参数和ref参数和函数的返回值一起返回,并且调用函数时out参数不需要传入,可以使用别的变量来接受该out参数,比如:

out参数,比如:

对于ref参数,如下:

ref参数,如下:

可以看到,其在lua中的用法和out参数是一样的。但是,传递进去的参数并没有变化,这一点和在C#中的用法是不一样的。

  • 事件处理,添加和删除事件委托

     LuaInterface为Event提供了Add和Remove函数来注册和移除事件处理函数。Add函数传入一个Lua函数,将其转换为一个CLR委托(delegate),并返回这个委托。如下:

并返回这个委托。如下:

  •  

猜你喜欢

转载自blog.csdn.net/Tong1993222/article/details/82983493
今日推荐