C# 与 lua 交互(Xlua 机制)

4 篇文章 0 订阅

https://www.cnblogs.com/hiker-online/p/13603400.html

lua与C交互:基于栈操作,lua调用C函数时,需要写个封装函数,从栈上取出调用参数,调用C函数后把结果放到栈上;C要调用lua函数,也把参数放到栈上,用luaAPI完成调用后,从栈上取出结果
Xlua lua调用C#


1. 没有生成静态代码,反射调用

  • a.把C#对象映射到lua的userdata,userdata只保留一个信息,就是这个对象在C#侧的objects_pool的索引
  • b.根据obj获取其ClassType,根据type与调用函数(位置栈里边index2),通过反射获取实际执行的MethodInfo
  • c.根据MethodInfo构造一个满足LuaCSFunction的delegate并压栈
  • d.delegate构造,根据MethodInfo,取得args信息,根据args从栈中取出赋值,反射调用函数后把结果压栈;GetAsType是把栈上Lua对象转换成指定类型的C#对象,PushCsObject是把一个C#对象按映射规则压到Lua栈上
  • e.将统一的反射调用方法objectIndex设置为所有C#对象的metatable的__index

lua_call_Csharp示例:

[MonoPInvokeCallback(typeof(LuaCSFunction))]
public static int objectIndex(RealStatePtr L)
{
object obj = objects_pool[GetCSObjectId(L, 1)];
Type objType = obj.GetType();
string index = LuaAPI.lua_tostring(L, 2);
MethodInfo method = objType.GetMethod(index);
PushCSFunction(L, (IL) =>
{
ParameterInfo[] parameters = method.GetParameters();
object[] args = new object[parameters.Length];
for(int i = 0; i < parameters.Length; i++)
{
args[i] = GetAsType(IL, i + 2, parameters[i].ParameterType);
}
object ret = method.Invoke(obj, args);
PushCSObject(IL, ret);
return 1;
});
return 1;
}

Csharp_call_lua示例:

public object[] Call(params object[] args)
{
int old_top = LuaAPI.lua_gettop(L);
LuaAPI.lua_getref(L, func_ref);
for(int i = 0; i < args.Length; i++)
{
Type arg_type = args[i].GetType();
if (arg_type == typeof(double))
{
LuaAPI.lua_pushnumber(L, (double)args[i]);
}
// ... other c# type
}
LuaAPI.lua_call(L, args.Length, -1);
object[] ret = new object[LuaAPI.lua_gettop(L) - old_top];
for(int i = 0; i < ret.Length; i++)
{
int idx = old_top + i + 1;
if(LuaAPI.lua_isnumber(L, idx))
{
ret[i] = LuaAPI.lua_tonumber(L, idx);
}
// ... other lua type
}
return ret;
}


2. 非反射,静态生成代码


反射带来的问题:

  • a.拆装箱开销
  • b.stripping引用的反射失效
  • c.泛型方法,触发JIT,引起IOS异常
  • d.失去静态检查好处

非反射做法:用反射的方式,用工具生成要用在lua侧调用的类的,类似反射调用代码(见lua_call_Csharp示例),只是去除了里边的反射内容,因为针对每个类是确定的,不需要用反射
静态代码的问题:

  • a.生成时,有宏定义的方法,如Editor会有问题
  • b.生成的代码,增大编译后的代码大小,尤其il2cpp,相应地增加包体大小

参考:https://gameinstitute.qq.com/community/detail/105650

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值