博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
toLua踩坑
阅读量:4561 次
发布时间:2019-06-08

本文共 5510 字,大约阅读时间需要 18 分钟。

新博客:

欢迎关注,同步更新

toLua踩坑篇

最近工作得用Lua实现逻辑,桥梁用的toLua,踩了很多坑,在这里记录一下。

坑~toLua解析Lua属性

首先我们给出Lua文件的内容,基于toLua Examples 04修改:

print('Objs2Spawn is: '..Objs2Spawn)var2read = 42varTable = {1,2,3,4,5}varTable.default = 1varTable.map = {}varTable.map.name = "map"meta = {name = "meta"}setmetatable(varTable, meta)function TestFunc()    print('get func by variable')endfunction varTable.func()    print("获取table中的函数")end

在展示坑之前先看看使用toLua,下面是解析全局变量的代码:

LuaState lua = new LuaState();Debug.Log(lua["全局变量名"]);

缓存成函数类LuaFunction:

LuaFunction func = lua.GetFunction("函数名");

缓存成表类LuaTable:

LuaTable table = lua.GetTable("表名");

那么下面开始踩坑,上代码:

// 声明lua解析器对象LuaState lua = new LuaState();lua.Start();// 添加lua执行路径lua.AddSearchPath(Application.dataPath + "/Lua");// 将Objs2Spawn存到lua的全局变量中并赋值lua["Objs2Spawn"] = 5;// 寻找文件并执行,如找到则返回一个对象。lua.DoFile("CallLuaFunction.lua");// 寻找文件并执行,第一次生成对象返回,之后返回之前生成过的对象。lua.Require("AccessingLuaVariables");// 通过LuaState访问Debug.Log(lua["var2read"]); // 输出-> 42Debug.Log(lua["varTable.default"]); // 输出-> 1// 直接利用LuaState获取nameDebug.Log(lua["varTable.map.name"]); // 输出-> mapLuaFunction func = lua["TestFunc"] as LuaFunction;func.Call();func = lua["varTable.func"] as LuaFunction;func.Call();func.Dispose();//cache成LuaTable访问LuaTable table = lua.GetTable("varTable");Debug.Log(table["default"]); // 输出-> 1// 利用Table获取name,有BugDebug.Log(table["map.name"]); // 输出-> NullLuaTable table1 = table.GetTable
("map");// 利用Table的Table获取nameDebug.Log(table1["name"]); // 输出-> map

最后的结果为:

Img

图中显示代码table["map.name"]的结果为Null,这里是toLua的一个bug,在缓存成table的时候处理table中的table有些问题。解决方式上面的代码也给了,就是从table中再获取table,实在是非常的麻烦,还有个简单的方式为直接利用LuaState获取。

坑~Lua函数解析

这里利用的是toLua Examples 03的内容作了一些修改,首先还是看Lua代码:

CallLuaFunction = {}function CallLuaFunction.func1()    print("Call Lua Function")endfunction CallLuaFunction.func2(num1, num2)    print("执行func2")    return num1 + num2endfunction CallLuaFunction.func3(num)    return num + 1endfunction CallLuaFunction.func4(num)    print("执行func4 " .. num)endfunction CallLuaFunction:func5()    self.a = 1    self.b = 2    print(self.a .. " " .. self.b)end

这里一共有5个函数,我们分别针对这五个函数的解析做一些展示。首先是func1,这个函数没有任何的参数也没有返回值,所以调用它很简单(这里假设已经做完lua的建立和释放工作):

// 获取Lua函数LuaFunction func = lua.GetFunction("CallLuaFunction.func1");// 执行函数,无返回值,最多支持9个参数func.Call();

对于func2的函数,有两个参数和返回值,这里给出了示例中的4种执行方式,这里坑就来了

// 注:必须进行委托初始化才能执行方式1,3,4DelegateFactory.Init();func = lua.GetFunction("CallLuaFunction.func2");if (func != null){    // 第一种方式    // 执行函数,有返回值,最多支持9个参数1个返回值    int num = func.Invoke
(10, 20); Debug.Log(num); // 第二种方式 num = CallFunc(func); Debug.Log(num); // 第三种方式 // 向LuaFunction中添加委托,利用委托实现函数返回 // 注:此委托ToLua作者并没有给,所以得自己补充 // 作者只给了Func
的委托 Func
luaFunc = func.ToDelegate
>(); num = luaFunc(10, 20); Debug.Log(num); // 第四种方式 // 直接利用LuaState执行函数,最多6个参数1个返回值 num = lua.Invoke
("CallLuaFunction.func2", 10, 20, true); Debug.Log(num);}private int CallFunc(LuaFunction func){ // 函数开始 func.BeginPCall(); // 传第一个参 func.Push(10); // 传第二个参 func.Push(20); // 执行函数 func.PCall(); // 检查返回值 int num = (int)func.CheckNumber(); // 结束函数 func.EndPCall(); return num;}

再执行到第三种方式的时候会报错,提示no register(未注册),这是为什么呢?因为代码中会注册委托,再进行调用,而Func<int, int, int>并没有被注册,所以报错了。这里我们知道原因了,那就自己加一个注册呗,说干就干:

DelegateFactory脚本的Register方法控制的委托注册在里面加上一行:

DelegateTraits
>.Init(factory.System_Func_int_int_int);

同是在DelegateFactory脚本中我们添加System_Func_int_int_int函数:

public System.Func
System_Func_int_int_int(LuaFunction func, LuaTable self, bool flag){ if (func == null) { System.Func
fn = delegate (int param0, int param1) { return 0; }; return fn; } if (!flag) { System_Func_int_int_int_Event target = new System_Func_int_int_int_Event(func); System.Func
d = target.Call; target.method = d.Method; return d; } else { System_Func_int_int_int_Event target = new System_Func_int_int_int_Event(func, self); System.Func
d = target.CallWithSelf; target.method = d.Method; return d; }}

到这里我们还缺少System_Func_int_int_int_Event类,也同是在DelegateFactory脚本中添加:

class System_Func_int_int_int_Event : LuaDelegate{    public System_Func_int_int_int_Event(LuaFunction func) : base(func) { }    public System_Func_int_int_int_Event(LuaFunction func, LuaTable self) : base(func, self) { }    public int Call(int param0, int param1)    {        func.BeginPCall();        func.Push(param0);        func.Push(param1);        func.PCall();        int ret = (int)func.CheckNumber();        func.EndPCall();        return ret;    }    public int CallWithSelf(int param0, int param1)    {        func.BeginPCall();        func.Push(self);        func.Push(param0);        func.Push(param1);        func.PCall();        int ret = (int)func.CheckNumber();        func.EndPCall();        return ret;    }}

坑就这样踩过去了,运行以下,你会发现不会报错并且执行也是正确的了。

接下来是func3函数,一个参数,这个就不用多说了与func2一样的。

之后是func4函数,这里就展示一下func2中的最后一种执行方式,不过没有返回值:

lua.Call
("CallLuaFunction.func4", 10, true);

最后的func5就很神奇了,哪里神奇呢?你注意到表名和函数名的连接处用的是":"了么,这里与"."的区别就是会传入self,相当于C#中的this,那又会说了func5不是没有参数么,因为self是隐式的传入,如果你从C#调用它,必须得传这个参数。坑,这里用GetTable解决一下,感觉很麻烦,不过toLua应该是内置了":"函数的形式。

LuaTable table = lua.GetTable("CallLuaFunction");lua.Call
("CallLuaFunction.func5", table, true);Debug.Log(table["a"]);

转载于:https://www.cnblogs.com/SHOR/p/9465185.html

你可能感兴趣的文章
aop动态代理 事务 threadlocal
查看>>
asp.net web api 2 对跨域资源共享的支持
查看>>
codeforces 510c (拓扑排序)
查看>>
优化算法索引
查看>>
【Linux】more命令
查看>>
8大你不得不知的Android调试工具
查看>>
第二阶段冲刺_个人总结09
查看>>
移走mysql data目录,及常见mysql启动问题
查看>>
模板库Mako的语法
查看>>
快速寻找满足条件的两个数(待完成)
查看>>
##JSP禁用缓存的方式
查看>>
hdu 4720 Naive and Silly Muggles
查看>>
pc端元素拖拽
查看>>
Sublime Text3使用Package Control 报错There Are No Packages Available For Installation
查看>>
判断连通图是否有环(并查集)
查看>>
汽车之家面试题2016
查看>>
POJ-数据结构-优先队列模板
查看>>
【HAOI2006】旅行(并查集暴力)
查看>>
css实现文本超出部分省略号显示
查看>>
留言板
查看>>