7-30 1,092 views
要擅于去看lua文档,源码, 部分翻译来自云风, ps C#也开源了 :)
正数表示相对于栈底的位置,栈底是1 ,负数表示相对于栈顶的位置,栈顶是-1;
入栈
lua_getfield (lua_State *L, int index, const char *k);
将t[k] 的值压栈, 这里的 t 是栈索引
index 处的值, 可能触发__index
lua_getglobal (lua_State *L, const char *name)
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)
把全局变量 name 里的值压栈
lua_getmetatable (lua_State *L, int index);
如果索引index处的值有元表,则将其元表压栈,返回 1 。 否则不会将任何东西入栈,返回 0
lua_gettable (lua_State *L, int index)
将t[k]值压栈, t是栈index处值, k是栈顶值,.这个函数会弹出栈顶的key值(把结果放在栈上相同位置)可能触发__index
lua_rawget (lua_State *L, int index)
同上,不会触发__index
lua_rawgeti (lua_State *L, int index, lua_Integer n)
把 t[n] 的值压栈, 这里的 t 是指给定索引 index 处的一个值, 不出发__index
lua_gettop (lua_State *L)
返回栈中元素的个数,同时也是栈顶元素的索引,0表示栈为空
lua_insert (lua_State *L, int index);
栈顶元素移动到指定的有效索引index处, 依次移动这个索引之上的元素
lua_newtable (lua_State *L)
创建空表压栈等价于 lua_createtable(L, 0, 0)
lua_pushnumber (lua_State *L, lua_Number n)
lua_pushstring (lua_State *L, const char *s)
浮点数n压栈
s指向的字符串压栈, 返回内部副本的指针, s为Null则将nil压栈返回Null
lua_pushvalue (lua_State *L, int index)
复制index位置的元素压入栈顶
lua_tostring (lua_State *L, int index)
把索引index处(字符串或数字)转换为C字符串, 否则返回NUll
出栈
lua_setfield (lua_State *L, int index, const char *k);
做 t[k] = v 的操作, t 是栈索引 index 处的值, 而 v 是栈顶的值,这个函数将把这个值弹出堆栈,可能触发__newindex
lua_setglobal (lua_State *L, const char *name)
从栈上弹出一个值作为全局变量name的新值
lua_setmetatable (lua_State *L, int index)
将表弹出栈设置为索引index处值的原表
lua_settable (lua_State *L, int index)
做t[k] = v 的操作, t是索引index处的值,v是栈顶的值, k是栈顶之下的值, 这个函数会将键值都从栈弹出, 可能会出发__newindex
lua_rawset (lua_State *L, int index)
同上, 不触发__newindex
lua_rawseti (lua_State *L, int index, lua_Integer i)
等价于 t[i] = v, 这里的 t 是指给定索引 index 处的一个值, 而 v 是栈顶的值。函数将把这个值弹出栈, 不会触发__newindex
lua_settop (lua_State *L, int index)
把栈顶设为这个索引index,如果新栈顶比原来大,超出部分填nil, index= 0时,清空栈
lua_pop (lua_State *L, int n)
从栈中弹出 n 个元素
lua_remove (lua_State *L, int index)
移除栈索引index处的值, 将此索引之上的向下移动填充
lua_call (lua_State *L, int nargs, int nresults)
nargs为参数个数, 先压入函数,再按顺序压入参数,调用时(会从栈弹出所有参数和函数),再按顺序压入返回值(最后的结果在栈顶)nresults 被设置成 LUA_MULTRET十所有返回值都被压栈
lua: a = f("how", t.x, 14) C: lua_getglobal(L, "f"); lua_pushliteral(L, "how"); /* 1st argument */ lua_getglobal(L, "t"); lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ lua_remove(L, -2); /* remove 't' from the stack */ lua_pushinteger(L, 14); /* 3rd argument */ lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result,push result to the stack*/ lua_setglobal(L, "a"); /* set global 'a' */
int lua_pcall (lua_State *L, int nargs, int nresults, int msgh)
如果有错误发生(返回值非0), lua_pcall 会捕获它, 然后把唯一的值(错误消息)压栈,然后返回错误码。 如果 msgh 是 0 ,返回在栈顶的错误消息就和原始错误消息完全一致。 否则, msgh 就被当成是 错误处理函数在栈上的索引位置.在发生运行时错误时, 这个函数会被调用而参数就是错误消息。错误处理函数的返回值将被 lua_pcall 作为错误消息返回在堆栈上。
Tolua为例, lua中调用gameobject.transform.position = pos流程简析
//从lua到C#基本流程:lua userdata->lua metatable->C# warp->lua id->C# translator->C#对象 //注册 L.BeginClass();//UnityEngine_GameObjectWrap L.RegVar("transform", get_transform, null);//这些方法会被注册到对应metatable中 LuaDLL.tolua_variable(L, name, fget, fset); //C tolua_variable RegVar调用,注册对应C方法到lua LUALIB_API void tolua_variable(lua_State *L, const char *name, lua_CFunction get, lua_CFunction set) { ... lua_pushstring(L, name); tolua_pushcfunction(L, get); //做metatable["transform"] = get操作 lua_rawset(L, -3); ...ga } //调用 gameobject.transform //访问userdata的metatable, 找到对应c方法 UnityEngine_GameObjectWrap .get_transform // 通过MonoPInvokeCallbackAttribute标签, 使C回调回C# int udata = LuaDLL.tolua_rawnetobj(L, stackPos); //C tolua_rawnetobj 把lua中的userdata变成c#可以辨认的id LUALIB_API int tolua_rawnetobj(lua_State *L, int index) { int* udata = (int*)lua_touserdata(L, index);//如果index处值为int直接作为id返回 if (udata != NULL) { return *udata; } else if (lua_istable(L, index)) { lua_pushvalue(L, index); lua_pushlightuserdata(L, &vptr);//如果是个table, 找到userdata lua_rawget(L, -2); if (lua_isuserdata(L, -1))//把栈顶userdate替换到table位置 { lua_replace(L, index); udata = (int*)lua_touserdata(L, index);//转换userdata为id返回 if (udata != NULL) { return *udata; } } else { lua_pop(L, 1); } } return -1; } ObjectTranslator.TryGetValue(id) //用这个id,从ObjectTranslator中获取C#的gameobject对象 gameobject.transform //真正C#拿到transform ObjectTranslator.AddObject //如果之前未保存过,给transform分配一个id,id这个id会在lua中用来代表这个transform,transform要保存到ObjectTranslator供未来查找 LuaDLL.tolua_pushnewudata(L, reference, index); //C tolua_pushnewudata LUALIB_API void tolua_pushnewudata(lua_State *L, int metaRef, int index) { lua_getref(L, LUA_RIDX_UBOX);//ubox表压栈, 值弱引用,存放userdata, 下次如果同样userdata直接从这里拿 tolua_newudata(L, index);//在lua分配一个userdata,把id存进去 lua_getref(L, metaRef);//拿到类型的metatable压栈 lua_setmetatable(L, -2);//userdata附上metatable,让你可以transform.position这样使用它 lua_pushvalue(L, -1);//栈顶放上transfrom返回 lua_rawseti(L, -3, index);//将userdata以index为id, 保存到ubox中 lua_remove(L, -2); } //赋值 UnityEngine_TransformWrap.set_position LuaDLL.tolua_rawnetobj(L, stackPos) ObjectTranslator.TryGetValue(id) LuaDLL.tolua_getvec3 //得到pos transform.position = new Vector3(x,y,z) //真正赋值
版权属于: CrazyStone Entertainment
原文地址: https://www.crazystonent.com/2020/07/30/lua%e5%a0%86%e6%a0%88%e6%93%8d%e4%bd%9c/
转载时必须以链接形式注明原始出处及本声明。