C#与lua的相互调用

700 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情

Lua是一种很好的扩展性语言,Lua解释器被设计成一个很容易嵌入到宿主程序的库。LuaInterface则用于实现Lua和CLR的混合编程 。

一、C#调用Lua

1.1 编译tolua.dll

tolua C 起到承上启下的作用,是C#和lua的中间层,在和C#交互方面,作为非c#托管代码,会提供一些函数让c# DllImport,c#会通过Marshal等与非托管代码交互

还有一些lua的扩展库,比如 cjson、LuaSocket、sqlite3、lpeg、bit、pbc等手机游戏常用库,这些库扩展了lua的能力。

windows平台叫做tolua.dll;

android叫做libtolua.so;

mac平台叫tolua.bundle;

而iOS平台由于不允许使用动态库,所以会编译成静态库libtolua.a。

编译出tolua.dll,复制到unity的Plugins文件夹下,然后就可以在C#层以DllImport导入接口,然后就可以在C#层调用到C层的方法了。

1.2 C#调用Lua文件
 //C# 层调用 lua层 demo    
 void Start()
    {
        LuaState m_LuaState= new LuaState();//建立Lua虚拟机       
        m_LuaState.Start();//启动虚拟机
       //1. 使用string调用Lua        
       string luaString = @"print('这是一个使用DoString的Lua程序')";
       m_LuaState.DoString(luaString);

       //2. 使用文件调用Lua        
       //手动添加一个lua文件搜索地址        
       m_LuaState.AddSearchPath(string.Format("{0}/{1}", Application.dataPath, "Lua"));

        //读取main.lua文件        
        m_LuaState.DoFile("main");// 方法1        
        m_LuaState.Require(luaFile);// 方法2        
        m_LuaState.Dispose();//使用完毕回收虚拟机        
        Debug.LogFormat("当前虚拟机状态:{0}", null == m_LuaState);//验证虚拟机状态   
    }

ToLua直接调用Lua代码的方式有两种:DoString、DoFile。这两个只是运行一次,运行之后保存在缓存中

此外还有一个Require方法,这个方法和前两个方法不同的是,ToLua会将调用的Lua文件载入Lua栈中

在上述代码中要注意,使用DoFile和Require方法时,要手动给目标文件添加一个文件搜索位置。

1.3 C#中调用Lua变量/函数

上面实现了C#调用Lua文件和string,其实对于ToLua而且,直接调用string和文件并没有本质区别,最后都会转换成byte[]进行载入。

接下来实现一下ToLua调用指定Lua变量和函数

//找到mian方法并调用

LuaFunction main = m_LuaState.GetFunction("main");   

main.Call();

main.Dispose();

main = null;

二、Lua调用C#

在Lua中访问C#中的属性和方法。

Lua代码中,访问C#对象的属性的方式和访问table的键索引一样,比如obj.name或者 obj["name"]。

Lua代码中,访问C#对象的普通函数的方式和调用table的函数一样,比如obj:method1()。

luanet.load_assembly("lelelua")

Program=luanet.import_type("lelelua.Program")

program1=Program()

print(program1.name)

program1:TestMethod()

   public string name = "乐乐爱学习";

         public void TestMethod()

         {

             Console.WriteLine("C#中的方法");

         }

在Lua中访问C#中的方法-特殊情况,注意有两个返回值

 luanet.load_assembly("lelelua")

 Program=luanet.import_type("lelelua.Program")

 program1=Program()

 void,strlength=program1:TestOut("leleaixuexi")

 print(strlength)

   public void TestOut(string name, out int count)

   {

      count = name.Length;

    }

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

ref参数需要传入,返回一个table有两个值(value1,value2)。

当有重载函数的时候,调用函数会自动匹配第一个能匹配的函数。

可以使用get_method_bysig函数得到C#中指定类的指定参数的函数用法。

   luaMethod= get_method_bysig(Obj,"CSharpMethod","System.String")

        luaMethod("siki")

在Lua中注册C#中的事件委托(event delegate)。

在Lua中通过Add方法或者Remove方法把一个Lua的函数注册或者注销从C#中的事件委托中。

  function method()
   end
   obj.SomeEvent:Add(methodname(不用带引号))