toluaframework中C#怎么调用Lua的方法
- 问题
-
- Util.CallMethod
- LuaManager.CallFunction
- LuaFunction.LazyCall
- 解决方案
-
- LuaFunction脚本
- 无GC消耗的调用
- 用法总结
问题
用过luaframework框架的人应该都知道框架提供了Util的工具类,工具类提供了一个方法就是Util.CallMethod的方法,方便Unity中直接调用lua层的方法。
Util.CallMethod
///
/// 执行Lua方法
///
public static object[] CallMethod(string module, string func, params object[] args)
{
LuaManager luaMgr = AppFacade.Instance.GetManagerLuaManager>(ManagerName.Lua);
if (luaMgr == null)
{
Debug.LogError("lua模块“" + module + "”未被找到");
return null;
}
return luaMgr.CallFunction(module + "." + func, args);
}
LuaManager.CallFunction
下面这里使用的框架提供的方法,但是这个方法是有GC的,我们在进入到luaMgr.CallFunction中查看一下
// Update is called once per frame
public object[] CallFunction(string funcName, params object[] args) {
LuaFunction func = lua.GetFunction(funcName);
if (func != null) {
return func.LazyCall(args);
}
return null;
}
从上面的代码中我们可以看到实际上他调用的是LazyCall(),这个方法的返回值是object[],这必然是需要我们自己拆箱装箱,有GC的操作,尽可能避免拆箱装箱可以减少性能的消耗。
LuaFunction.LazyCall
这个方法作者也提示了是有GC的,这里让我们使用的是Invoke的方法调用,这样我们不需要有装箱拆箱的转换操作,这里可以直接转换成我们需要的数据。
//慎用, 有gc alloc
[System.Obsolete("LuaFunction.LazyCall() is obsolete.Use LuaFunction.Invoke()")]
public object[] LazyCall(params object[] args)
{
BeginPCall();
int count = args == null ? 0 : args.Length;
if (!luaState.LuaCheckStack(count + 6))
{
EndPCall();
throw new LuaException("stack overflow");
}
PushArgs(args);
PCall();
object[] objs = luaState.CheckObjects(oldTop);
EndPCall();
return objs;
}
解决方案
这里我只举一个例子写一个两个参数的方法,多个参数的方法模仿我这个自己写就好了,需要多少参数写多少个方法即可
LuaFunction脚本
我们先看看这个脚本作者给我们提供了什么
这里作者给我们提供了无返回值的多参数Call的方法,也提供了有返回值的多参数Invoke
无GC消耗的调用
找到LuaManager脚本中原始有GC消耗的脚本,在他下方我们加两个多态写法
添加两个无GC消耗的多态方法
// Update is call服务器托管网ed once per frame 原始有GC的方法
public object[] CallFunction(string funcName, params object[] args) {
LuaFunction func = lua.GetFunction(funcName);
if (func != null) {
return func.LazyCall(args);//这里有GC
}
return null;
}
//有返回值并且有两个参数的无GC调用方法
public R CallFunctionT1,T2,R>(string funcName, T1 t1,T2 t2)
{
LuaFunction func = lua.GetFunction(funcName);
if (func != null)
{
return func.InvokeT1,T2,R>(t1,t2);
}
return default;
}
//无返回值并且有两个参数的无GC调用方法
public void CallFunctionT1, T2>(string funcName, T1 t1, T2 t2)
{
LuaFunction func = lua.GetFunction(funcName);
if (func != null)
{
func.CallT1, T2>(t1, t2);
}
}
打开Util工具类脚本,找到原始有GC的工具类调用方法
在这下方我们写两个调用方法封装一下
///
/// 执行Lua方法 有GC
///
public static object[] CallMethod(string module, string func, params object[] args)
{服务器托管网
LuaManager luaMgr = AppFacade.Instance.GetManagerLuaManager>(ManagerName.Lua);
if (luaMgr == null)
{
Debug.LogError("lua模块“" + module + "”未被找到");
return null;
}
return luaMgr.CallFunction(module + "." + func, args);
}
//无返回值无GC两个参数的方法
public static void NoGCCallMethodT1, T2>(string module, string func, T1 t1, T2 t2)
{
LuaManager luaMgr = AppFacade.Instance.GetManagerLuaManager>(ManagerName.Lua);
if (luaMgr == null)
{
Debug.LogError("lua模块“" + module + "”未被找到");
}
luaMgr.CallFunction(module + "." + func, t1 ,t2);
}
//有返回值无GC两个参数的方法
public static R InvokeMethodT1, T2, R>(string module, string func, T1 t1, T2 t2)
{
LuaManager luaMgr = AppFacade.Instance.GetManagerLuaManager>(ManagerName.Lua);
if (luaMgr == null)
{
Debug.LogError("lua模块“" + module + "”未被找到");
return default;
}
return luaMgr.CallFunctionT1, T2, R>(module + "." + func, t1, t2);
}
用法总结
下面是原始有GC的调用方法和无GC的调用方法,调用参考
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
Mysql存储-EAV模式 最近又又又搞一点新东西,要整合不同业务进行存储和查询,一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键,需要充分考虑你需要使用的字段、使用场景,当数据结构设计完成后便会发现eav模型需要多次…