Lua CAPI函数说明

学习时出现的疑问
1.luaL_loadstring()入栈了什么东西
答:入栈了一个module,可以被pcall调用

2.为什么循环100次入栈,程序就崩了,是不是因为栈满了
3.为什么调用lua_close的时候程序会崩

4.入栈了userdata后,lua端怎么使用
答:参考 函数说明lua_newuserdata

5.pcall的返回值
答:0表示正常,非零则为异常,同时会将错误提示入栈

注意事项:

1.lua的栈中会有2种索引,一个是1为栈底,往上递增;一个是-1为栈顶,往下递减
2.如果API返回了一个int,则他需要为0才表示没有异常,其他结果都是异常
3.在使用lua_to…时,既可以用负索引,也可以用正索引
4.set表示出栈,get表示入栈
5.如果需要传递C对象,则这个对象要为userdata类型,使用lua_newuserdata创建
6.C#创建一个userdata的方法

Person person = new Person();	//自定义对象Person
GCHandle handle = GCHandle.Alloc(person);	//分配内存
IntPtr obj = GCHandle.ToIntPtr(handle);	//handle转成指针
IntPtr userdata = LuaAPI.lua_newuserdata(L, IntPtr.size);	//创建userdata
Marshal.WriteIntPtr(userdata, obj);	//把对象写入userdata中

7.C#获取userdata的方法

IntPtr p = LuaAPI.lua_topointer(L, -2);	//userdata的位置
IntPtr dataPtr = Marshal.ReadIntPtr(p);	//获取到对象指针
GCHandle handle = GCHandle.FromIntPtr(dataPtr);	//转为C# GCHandle
object obj = handle.Target;	//Target就是对象
Person person = (obj as Person);

8.函数的返回值
入栈则表示lua返回值
C# return 0 表示函数有问题,不会返回任何数据。即使已经入栈了数据,也会被清掉。注意与pcall中的返回值相反,pcall返回0表示正常
return 1则表示函数执行正常,栈中的数据可以正常到lua端
如下:

private static int TestCClose(lua_State L)
{
	Console.WriteLine("C# 函数调用!");
	MyLib.lua_pushinteger(L, 7777);
	//return 0 返回0,函数异常,入栈的数据不会回到lua端中
	return 1;	//返回1,结果正常
}

函数说明

[-(nargs + 1), +(nresults|1), -]
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
出栈nargs+1,就是说如果没有参数时,他也会把当前栈顶出栈,如果栈顶不是函数则报错

[-(nargs + 1), +(nresults|1), -]
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
与lua中的调用函数调用一样,这里他会去调用栈顶。
如果栈顶是函数,则正常调用;如果不是函数,则调用报错。所以一般来说栈初始化完了后,栈中应该只剩下一开始加载的那个module

[-0, +1, m]
void *lua_newuserdata (lua_State *L, size_t size);
创建一个userdata,这个对象在创建后,不可以使用setfield等操作访问k,v,因为userdata没有这种操作,会让程序直接崩掉。
正确操作:1.创建一个元表meta,将k,v全都设置到元表上;2.把userdata的元表设置为meta

[-0, +1, m]
int luaL_newmetatable (lua_State *L, const char *tname)
创建元表到栈顶

[-1, +0, m]
int luaL_ref (lua_State *L, int t);
将栈顶数据转为引用并且出栈。一般操作是将一个函数注册到注册表中,方便其他地方获取这个函数。调用时会在注册表里生成一个key,并且把数据赋值到key里,同时返回这个key。使用rawgeti则可以将注册表的对应key值的数据入栈
比如:

//返回的funcRef其实是注册表的索引,如果想要获取这个函数
//则 LuaAPI.lua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, funcRef);
//rawgeti后会把函数放到栈顶
int funcRef = LuaAPI.luaL_ref(L, LuaAPI.LUA_REGISTRYINDEX);

这种方法可以将函数注册到C#委托或者事件中

[-0, +0, –]
void lua_close (lua_State *L);
销毁L创建的所有对象,并且释放L使用的所有动态内存。
如果没有及时销毁,会造成内存泄漏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
详细描述Lua和C之间相互传递Table类型数据 /* ====================================================== */ // 遍历Lua传入的Table类型参数, 获取它的Key/Value, 其关键操作是 lua_next() // lua_next() 返回1表示读取成功,返回0表示已经没有数据可读了 // lua_next() 会使用栈顶元素作为Key去定位本次需要取出Table里面的那个值对 // 如果Key=nil, 那就表示本次取出的是第一个元素 // 它会先将当前的这个Key弹出,然后将本次取出的Key/Value压入栈, Value在栈顶 // 一个比较隐晦的处理就是, 我们不应直接使用lua_tostring(L, -2)来读取Key // 因为lua_tostring()在Key类型不是字符串时, 它会修改栈上的Key数据 // 这样, 下次调用lua_next()时, 就会因为Key被修改了而导致错误 // 为此,先调用lua_pushvalue(L, -2),将它Copy一份到栈顶,对这个Copy进行lua_tostring() // 读取Key,Value到C变量里面后,将Value和Copy弹出,留着Key在栈顶,给下次lua_next()用 // // 指令及栈图变化如下: (假如Table的栈下标是Index) // 0. 刚进入函数时 ...Table, ... <--- 这里栈顶 // 1. lua_pushnil(L) ...Table, ..., nil <--- 这里栈顶 // 2. lua_next(L, Index) ...Table, ..., Key, Value <--- 这里栈顶 // 3. lua_pushvalue(L, -2) ...Table, ..., Key, Value, KeyCopy <--- 这里栈顶 // 4. lua_pop(L, 2), ...Table, ..., Key <--- 这里栈顶 // ... 如此重复2,3,4 // N. lua_next(L, Index)返回0 ...Table, ... <--- 这里栈顶 /* ====================================================== */

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值