LuaInterface的简单学习,CLR与Lua相互调用

    xiaoxiao2021-03-25  49

    简单介绍下CLR: CLR(公共语言运行库,Common Language Runtime),是一个可由多种编程语言使用的运行环境。CLR是 .NET Framework 的主要执行引擎。它的核心功能包括:内存管理,程序集加载,异常处理,安全性和线程同步。

    (一)Lua from the CLR 准备工作:

    1.LuaForWindows下载地址:http://pan.baidu.com/s/1kU8hiTL(这里测试的是LuaForWindows_v5.1.4-46,安装中包含一个“ SciTE”的编译器,可以用来执行lua程序) 2.LuaInterface下载地址:http://pan.baidu.com/s/1nuB0TgX(这里测试的是luainterface-1.5.3,这里资源比较多,代码比较完整) 3.测试环境:在VS2015中创建一个C#控制台应用程序(luainter),将luainterface-1.5.3压缩包中Built文件夹下面的LuaInterface.dll、luanet.dll直接拖入工程。然后找到已经创建的C#控制台应用程序,添加对LuaInterface.dll的引用。(注意…\bin\Debug文件夹下面,要包含LuaInterface.dll、luanet.dll ) *““““““““““““““““““““““““

    下面代码展示的功能: 1. CLR访问Lua的Global作用域 2. CLR新建Lua的table表 3. CLR执行Lua脚本代码和脚本文件DoString、DoFile

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LuaInterface; namespace luainter { class Program { static void Main(string[] args) { //创建一个Lua解释器,每个Lua实例都相互独立 Lua lua = new Lua(); //Lua的索引操作[]可以创建、访问、修改Global作用域,[]里面是变量名 lua["score"] = 66; lua["name"] = "shaco"; //创建一个空的table lua.NewTable("nilTab"); lua.DoString("score = 100; print(\"i am a lua string\")"); //执行文件Hello World.lua //lua.DoFile("D:\\Lua MyWork\\Hello World.lua"); //lua.DoFile("string.lua");//此时Lua脚本放在Debug目录下面 //返回score、name的值 object[] retVal = lua.DoString("return score,name"); for (int i = 0; i < retVal.Length; i++) { Console.WriteLine(retVal[i]); } //访问Global作用域的num和str double score = (double)lua["score"]; string name = (string)lua["name"]; Console.WriteLine("score = {0}", score); Console.WriteLine("name = {0}", name); Console.ReadKey(); } } }

    说下Lua和CLR中一些基础类型的对应:

    特殊类型:userdata(自定义类型) userdata,是一种用户自定义数据,用于表示一种由应用程序或C/C++语言库所创建的类型,可以将任意C/C++的任意数据类型的数据(通常是struct和指针)存储到Lua变量中调用。

    Lua里面生成的userdata从Lua传到CLR时转换成 LuaInterface.LuaUserData LuaTable和LuaUserData都有索引操作[],用来访问和修改域值,索引可以是string或number LuaFunction和LuaUserData都有call方法来执行函数,可传入多个任意参数并返回值。

    下面代码展示: Lua调用CLR的函数:使用RegisterFunction将CLR函数注册到Lua解释器中,供Lua调用。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LuaInterface; namespace luainter { //TestReg类 class TestReg { private int value = 0; public void TestRegFun(int num) { Console.WriteLine("TestReg.TestRegFun run! value = {0}",value = num); } public static void TestStatic() { Console.WriteLine("TestReg.TestStatic run!"); } } class Program { static void Main(string[] args) { Lua lua = new Lua(); TestReg obj = new TestReg(); //注册CLR普通方法到Lua中 lua.RegisterFunction("LuaTestRegFun", obj, obj.GetType().GetMethod("TestRegFun")); //注册CLR静态方法到Lua中 // 也可用 typeof(TestReg).GetMethod("TestRegFun") lua.RegisterFunction("LuaTestStatic", null, typeof(TestReg).GetMethod("TestStatic")); //调用方法 lua.DoString("LuaTestRegFun(10)"); lua.DoString("LuaTestStatic()"); Console.ReadKey(); } } }

    (二)CLR from Lua


    (1).加载和实例化CLR 类型 1.第一种:纯Lua脚本进行测试(在SciTE编辑器中)

    --请求连接 require "luanet" --加载CLR的类型 luanet.load_assembly("System.Windows.Forms") luanet.load_assembly("System.Drawing") --实例化CLR对象 Form = luanet.import_type("System.Windows.Forms.Form") StartPosition = luanet.import_type("System.Windows.Forms.FormStartPosition") print(Form) print(StartPosition)

    2.第二种:在C#工程中测试 在外部编写好Lua脚本,然后在C#工程中使用lua.DoFile接口运行lua脚本。这种方式很灵活,而且方便测试LuaInterface提供的各项功能。在这种情况下不需要 require “luanet”.因为已经手动将LuaInterface的引用添加到工程。lua脚本中直接使用luanet就可以访问接口了。

    luanet.load_assembly函数:加载CLR程序集 luanet.import_type函数:加载程序集中的类型 luanet.get_constructor_bysig函数:显示获取某个特定的构造函数

    下面展示的是在C#脚本中的代码

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LuaInterface; namespace luainter { class TestLuaAndC { public TestLuaAndC(string str) { Console.WriteLine("called TestLuaAndC(string str) str = {0}", str); } public TestLuaAndC(int num) { Console.WriteLine("called TestLuaAndC(int num) num = {0}", num); } public TestLuaAndC(int num1, int num2) { Console.WriteLine("called TestLuaAndC(int num1, int num2) num1 = {0}, num2 = {1}", num1, num2); } } class Program { public string name = "shaco"; public void Test_Method() { Console.WriteLine("called method."); } static void Main(string[] args) { //加载和实例化CLR类型 Lua lua = new Lua(); lua.DoFile("D:\\Lua MyWork\\TestLuaNet.lua"); //也可以把lua脚本直接放在Debug目录下 //lua.DoFile("TestLuaNet.lua"); Console.ReadKey(); } } }

    下面是lua脚本中的代码

    --加载自定义类型,先加载程序集,再加载类型 luanet.load_assembly("Testluainter") Testluaandc1 = luanet.import_type("luainter.TestLuaAndC") Testluaandc2 = luanet.import_type("luainter.Program") obj1 = Testluaandc1(2,3) obj2 = Testluaandc1("shaco") obj3 = Testluaandc1(3) Testluaandc = Testluaandc2() --访问字段 print(Testluaandc.name) --访问方法 print(Testluaandc:Test_Method()) --手动匹配构造函数 Testluaandc_cons3 = luanet.get_constructor_bysig(Testluaandc1, 'System.Int32') obj3 = Testluaandc_cons3(3)

    Testluainter是建立的程序集名字,这个可以在工程属性中可以设置。luainter为测试代码的命名空间。

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

    LuaInterface从上往下匹配第一个能够匹配到的函数,在这个过程中,number自动匹配到string,numerical string(数字字符串)自动匹配number。所以,Testluaandc(3)匹配到了string参数当中。

    如果要手动匹配某个构造函数,则可以使用luanet.get_constructor_bysig();


    (2)访问CLR类型中的字段和方法 在Lua代码中访问CLR类型的字段,和访问table的索引一样,obj.text、obj[“text”] 在Lua代码中访问LR类型的方法,和调用table的函数一样,obj:methodname()

    还有几种在访问时候可能出现的特殊情况:

    a. 当有重载函数时候,函数的匹配过程会和上面提到的构造函数的匹配过程一样,自动匹配第一个能够匹配上的函数。如果需要指定某个特定的函数,可以使用get_constructor_bysig来指定函数。

    setMethod = luanet.get_constructor_bysig(obj,"System.Int32") setMethod(123)

    b. 当函数中有out 或 ref 参数时,out参数和ref参数和函数的返回值一起返回,并且在调用的时候out参数不需要传入。

    C#中测试代码

    using System; using LuaInterface; namespace luainter { class Program { public void TestOut(string name, out int count) { Console.WriteLine(name); count = name.Length; } public void TestRef(string name, ref int count) { Console.WriteLine(name); Console.WriteLine(count); count = name.Length; } static void Main(string[] args) { //加载和实例化CLR类型 Lua lua = new Lua(); lua.DoFile("D:\\Lua MyWork\\TestLuaNet.lua"); //也可以把lua脚本直接放在Debug目录下 //lua.DoFile("TestLuaNet.lua"); Console.ReadKey(); } } }

    Lua脚本中测试代码

    luanet.load_assembly("Testluainter") Testluaandc2 = luanet.import_type("luainter.Program") Testluaandc = Testluaandc2() void, num = Testluaandc:TestOut("shaco") print(void,num) void, num = Testluaandc:TestRef("shaco",13) print(void,num)

    测试结果

    转载请注明原文地址: https://ju.6miu.com/read-50134.html

    最新回复(0)