找回密码
 立即注册
查看: 300|回复: 1

【Lua与C#交互①】Lua中的栈

[复制链接]
发表于 2021-8-11 14:36 | 显示全部楼层 |阅读模式
Lua是用C写的编程语言,它提供了一系列的API供用户可以在C里面调用,详见参考手册


在unity使用的xlua或者tolua等lua都是对Lua进行了封装,帮我们搭好C#到Lua这个桥梁。之所以要学习Lua和C#交互,是为了让我们更好的掌握Lua,从而不停留在只会用轮子的阶段。这篇文章是系列第一篇,所以会讲解一个最简单的例子。
<hr/>首先,Lua和C++/C/C#交互的时候内部会维护一个堆栈。 请大家注意图上标记的索引,Lua通过索引来拿到栈里面的数据,这些数据包括functiontable数值stringbool等。 - 1代表栈底,往上递增 - -1代表栈顶,往下递减


OK,那么接下来我们来写代码。首先将xLua或者toLua或者其它lua导入到unity工程。我这边使用的是xLua,其它Lua也会有类似的接口可以调用。 先上完整代码,结果是控制台会打印 756915370 这段数字。
using UnityEngine;
using System.Collections;
using System;
using LuaAPI = XLua.LuaDLL.Lua;

public class Test : MonoBehaviour
{
    IntPtr L;

    double num = 756915370;

    // Use this for initialization
    void Start()
    {
        L = LuaAPI.luaL_newstate();
        LuaAPI.lua_pushnumber(L, num);
        if(LuaAPI.lua_isnumber(L, 1))
        {
            Debug.Log(LuaAPI.lua_tonumber(L, 1));
        }
        LuaAPI.lua_close(L);
    }
<hr/>让我们一行行来看。
L = LuaAPI.luaL_newstate();
luaState的概念

luaState 中放的是 lua 虚拟机中的环境表、注册表、运行堆栈、虚拟机的上下文等数据。可以理解为我们写代码常用的各种manager类。在xLua中luaState被封装成了LuaEnv类,在toLua中叫作LuaState
Intptr是C#的指针。返回一个Intptr的目的是为了让C#能够持有luaState的引用。关于Intptr可以看MSDN,或者看这篇文章
<hr/>下一行:
LuaAPI.lua_pushnumber(L, num);
对lua堆栈的操作

这一行没什么好说的,就是往栈顶添加数据。类似的函数还有lua_pushstringlua_pushboolean等,不过table的话是使用lua_createtable
<hr/>下一行:
if(LuaAPI.lua_isnumber(L, 1))
  {
      Debug.Log(LuaAPI.lua_tonumber(L, 1));
  }
根据索引找到数据

这个就用到了之前说的,1代表栈底,因为我们只有一个数据,显然栈底就是我们想要的。先判断1这个位置的数据是不是数值,然后打印。
<hr/>最后:
LuaAPI.lua_close(L);
内存回收

最后一行代码就是取消对luaState的引用,以便下次GC能够回收这块内存。 说到内存,我顺带写一下今天看xLua源码学到的知识。
关于IDisposable和Dispose()

    实现了IDisposable的类,在GC时会调用Dispose方法。而Dispose方法是在另一个线程里跑的,所有实现了IDisposable的类所占用的内存在GC后不会立刻回收,而是等全部Dispose方法调用完之后回收。如果主线程想等Dispose的线程跑完之后再做一些事情,使用System.GC.WaitForPendingFinalizers()Dispose() 里面的代码需要考虑是否被多次调用,如果你在其它地方也调用类的Dispose() 的话,比如 OnDestroy() 等等。
<hr/>2020.4.29: 更新适用于tolua版本的代码
var num = 756915370;
IntPtr L = LuaDLL.luaL_newstate();
LuaDLL.lua_pushnumber(L,num);
//等于1说明是True
if (LuaDLL.lua_isnumber(L, 1) == 1)
{
     Debug.Log(LuaDLL.lua_tonumber(L,1));
}
LuaDLL.lua_close(L);
<hr/>2020.6.20:
将tolua删掉,替换成自己打包的lua。
LuaState和luaDLL由自己实现。
<hr/>github工程 对应的文件夹是Examples/01_Stack
系列文章:
【Lua与C#交互①】Lua中的栈_lua_水鸡的游戏开发学习笔记-CSDN博客
【Lua与C#交互②】加载Lua文件_lua_水鸡的游戏开发学习笔记-CSDN博客
【Lua与C#交互③】方法调用和错误处理函数_水鸡的游戏开发学习笔记-CSDN博客

qq群:891809847

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-8-11 14:37 | 显示全部楼层
堆栈介绍那里,写成-1是栈底
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 07:51 , Processed in 0.090821 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表