zoukankan      html  css  js  c++  java
  • Lua和C++交互 学习记录之二:栈操作

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍)

    部分内容查阅自:《Lua 5.3  参考手册》中文版 译者 云风 制作 Kavcc

     

    vs2013+lua-5.3.3

     

    1.理解栈

    ①C++通过lua虚拟机中的栈和lua进行交互。(相当于一个中间层)

    ②C++自己管理内存;lua自动垃圾回收;虚拟机知道在栈里的数据是否有被外部宿主程序使用,从而决定是否进行GC;

    ③C++的是静态类型;lua是动态类型;通过对静态类型的结构封装类似“Lua_Value”的类型,就能将数据放到栈中进行交互。

    ④栈是FILO的;C++可以操作栈的任何位置;在lua里操作每次操作的都是栈的顶部;

     

    下面就分两个主要部分进行介绍(C++和栈操作;以及Lua和栈操作)

    2.C++和栈之间操作相关函数

    ①c -> stack 将C++数据压到栈里函数:lua_pushxxx

     1 LUA_API void        (lua_pushnil) (lua_State *L);
     2 LUA_API void        (lua_pushnumber) (lua_State *L, lua_Number n);
     3 LUA_API void        (lua_pushinteger) (lua_State *L, lua_Integer n);
     4 LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
     5 LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
     6 LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
     7                                                       va_list argp);
     8 LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
     9 LUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
    10 LUA_API void  (lua_pushboolean) (lua_State *L, int b);
    11 LUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);
    12 LUA_API int   (lua_pushthread) (lua_State *L);

     

    ②stack -> c 判断栈里类型相关函数: lua_isxxx(lua_State *L, int idx)

    1 LUA_API int             (lua_isnumber) (lua_State *L, int idx);
    2 LUA_API int             (lua_isstring) (lua_State *L, int idx);
    3 LUA_API int             (lua_iscfunction) (lua_State *L, int idx);
    4 LUA_API int             (lua_isinteger) (lua_State *L, int idx);
    5 LUA_API int             (lua_isuserdata) (lua_State *L, int idx);
    6 LUA_API int             (lua_type) (lua_State *L, int idx);

     

    ③stack -> c 获取栈里数据相关函数:lua_toxxx (lua_State *L, int idx)

    1 LUA_API lua_Number      (lua_tonumberx) (lua_State *L, int idx, int *isnum);
    2 LUA_API lua_Integer     (lua_tointegerx) (lua_State *L, int idx, int *isnum);
    3 LUA_API int             (lua_toboolean) (lua_State *L, int idx);
    4 LUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);
    5 LUA_API size_t          (lua_rawlen) (lua_State *L, int idx);
    6 LUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);
    7 LUA_API void           *(lua_touserdata) (lua_State *L, int idx);
    8 LUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);
    9 LUA_API const void     *(lua_topointer) (lua_State *L, int idx);

     

     

    3.Lua和栈之间的操作相关函数

    ①从Lua中得到数据放到栈里进行操作:lua_getxxx

     1 LUA_API int (lua_getglobal) (lua_State *L, const char *name);
     2 LUA_API int (lua_gettable) (lua_State *L, int idx);
     3 LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
     4 LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
     5 LUA_API int (lua_rawget) (lua_State *L, int idx);
     6 LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
     7 LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
     8 
     9 LUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);
    10 LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
    11 LUA_API int   (lua_getmetatable) (lua_State *L, int objindex);
    12 LUA_API int  (lua_getuservalue) (lua_State *L, int idx);

    ②从栈里将数据写入到Lua中:lua_setxxx

    1 LUA_API void  (lua_setglobal) (lua_State *L, const char *name);
    2 LUA_API void  (lua_settable) (lua_State *L, int idx);
    3 LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
    4 LUA_API void  (lua_seti) (lua_State *L, int idx, lua_Integer n);
    5 LUA_API void  (lua_rawset) (lua_State *L, int idx);
    6 LUA_API void  (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
    7 LUA_API void  (lua_rawsetp) (lua_State *L, int idx, const void *p);
    8 LUA_API int   (lua_setmetatable) (lua_State *L, int objindex);
    9 LUA_API void  (lua_setuservalue) (lua_State *L, int idx);

     

    4.基本的栈操作

     1 //将一个可接受的索引 idx 转换为绝对索引 (即,一个不依赖栈顶在哪的值)
     2 LUA_API int   (lua_absindex)(lua_State *L, int idx);
     3 
     4 //取得栈中元素个数
     5 LUA_API int   (lua_gettop)(lua_State *L);
     6 
     7 //设置栈的大小为一个指定的值,而lua_settop(L,0)会把当前栈清空
     8 //如果指定的index大于之前栈的大小,那么空余的空间会被nil填充
     9 //如果index小于之前的栈中元素个数,则多余的元素会被丢弃
    10 LUA_API void  (lua_settop)(lua_State *L, int idx);
    11 
    12 //把栈中index所在位置的元素压入栈
    13 LUA_API void  (lua_pushvalue)(lua_State *L, int idx);
    14 
    15 //把从 idx 开始到栈顶的元素轮转 n 个位置。 对于 n 为正数时,轮转方向是
    16 //向栈顶的; 当 n 为负数时,向栈底方向轮转 - n 个位置。 n 的绝对值不可
    17 //以比参于轮转的切片长度大。
    18 LUA_API void  (lua_rotate)(lua_State *L, int idx, int n);
    19 
    20 //把fromidx处的元素copy一份插入到toidx,这操作不会修改fromidx处的元素
    21 LUA_API void  (lua_copy)(lua_State *L, int fromidx, int toidx);
    22 
    23 //确保堆栈上至少有 n 个额外空位。 如果不能把堆栈扩展到相应的尺寸,函
    24 //数返回假。 失败的原因包括将把栈扩展到比固定最大尺寸还大 (至少是几
    25 //千个元素)或分配内存失败。 这个函数永远不会缩小堆栈; 如果堆栈已经
    26 //比需要的大了,那么就保持原样
    27 LUA_API int   (lua_checkstack)(lua_State *L, int n);
    28 
    29 //交换同一个状态机下不同线程中的值。
    30 //这个函数会从 from 的栈上弹出n个值, 然后把它们压入to的栈上。
    31 LUA_API void  (lua_xmove)(lua_State *from, lua_State *to, int n);

     

    5.一些有用的宏操作(方便操作,提供了一些宏)

     1 //等价于调用 lua_tonumberx, 其参数 isnum 为 NULL。
     2 #define lua_tonumber(L,i)    lua_tonumberx(L,(i),NULL)
     3 
     4 //等价于调用 lua_tointegerx, 其参数 isnum 为 NULL。
     5 #define lua_tointeger(L,i)    lua_tointegerx(L,(i),NULL)
     6 
     7 //等价于调用 lua_tolstring , 其参数 len 为 NULL 
     8 #define lua_tostring(L,i)    lua_tolstring(L, (i), NULL)
     9 
    10 //从栈中弹出 n 个元素。
    11 #define lua_pop(L,n)        lua_settop(L, -(n)-1)
    12 
    13 //创建一张空表,并将其压栈。 它等价于 lua_createtable(L, 0, 0) 
    14 #define lua_newtable(L)        lua_createtable(L, 0, 0)
    15 
    16 //把 C 函数 f 设到lua的全局变量n 中
    17 #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
    18 
    19 //将一个 C 函数压栈。 这个函数接收一个 C 函数指针, 并将一个类型为
    20 //function 的 Lua 值压栈。 当这个栈顶的值被调用时,将触发对应的 C 函数。
    21 #define lua_pushcfunction(L,f)    lua_pushcclosure(L, (f), 0)
    22 
    23 //这个宏等价于 lua_pushlstring, 区别仅在于只能在 s 是一个字面量时才
    24 //能用它。 它会自动给出字符串的长度。
    25 #define lua_pushliteral(L, s)    lua_pushstring(L, "" s)
    26 
    27 //将全局环境压栈。
    28 #define lua_pushglobaltable(L)  
    29     ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
    30 
    31 //在栈的顶部的元素移动至index处
    32 #define lua_insert(L,idx)    lua_rotate(L, (idx), 1)
    33 
    34 //移除栈中index所在位置的元素
    35 #define lua_remove(L,idx)    (lua_rotate(L, (idx), -1), lua_pop(L, 1))
    36 
    37 //从栈顶弹出一个值,并把它设置到给定的index处
    38 #define lua_replace(L,idx)    (lua_copy(L, -1, (idx)), lua_pop(L, 1))
    39 
    40 #define lua_isfunction(L,n)    (lua_type(L, (n)) == LUA_TFUNCTION)
    41 #define lua_istable(L,n)    (lua_type(L, (n)) == LUA_TTABLE)
    42 #define lua_islightuserdata(L,n)    (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
    43 #define lua_isnil(L,n)        (lua_type(L, (n)) == LUA_TNIL)
    44 #define lua_isboolean(L,n)    (lua_type(L, (n)) == LUA_TBOOLEAN)
    45 #define lua_isthread(L,n)    (lua_type(L, (n)) == LUA_TTHREAD)
    46 #define lua_isnone(L,n)        (lua_type(L, (n)) == LUA_TNONE)
    47 #define lua_isnoneornil(L, n)    (lua_type(L, (n)) <= 0)

     

    6.为了调试方便,提供一个打印栈数据的函数方便使用

     

     1 void stack_dump(lua_State* L){
     2     printf("
    ------ stack dump begin ------
    ");
     3     for (int i = 1; i <= lua_gettop(L); ++i){
     4         int t = lua_type(L, i);
     5         switch (t){
     6         case LUA_TNONE:{
     7             printf("LUA_TNONE
    ");
     8         }break;
     9 
    10         case LUA_TNIL:{
    11             printf("LUA_TNIL
    ");
    12         }break;
    13 
    14         case LUA_TBOOLEAN:{
    15             printf("LUA_TBOOLEAN : %s
    ", lua_toboolean(L, i) ? "true" : "false");
    16         }break;
    17 
    18         case LUA_TLIGHTUSERDATA:{
    19             printf("LUA_TLIGHTUSERDATA
    ");
    20         }break;
    21 
    22         case LUA_TNUMBER:{
    23             //整形
    24             if (lua_isinteger(L, i)){
    25                 printf("LUA_TNUMBER integer : %lld 
    ", lua_tointeger(L, i));
    26             }
    27             else if (lua_isnumber(L, i)){
    28                 printf("LUA_TNUMBER number: %g
    ", lua_tonumber(L, i));
    29             }
    30         }break;
    31 
    32         case LUA_TSTRING:{
    33             printf("LUA_TSTRING : %s
    ", lua_tostring(L, i));
    34         }break;
    35 
    36         case LUA_TTABLE:{
    37             printf("LUA_TTABLE
    ");
    38         }break;
    39 
    40         case LUA_TFUNCTION:{
    41             printf("LUA_TFUNCTION
    ");
    42         }break;
    43 
    44         case LUA_TUSERDATA:{
    45             printf("LUA_TUSERDATA
    ");
    46         }break;
    47 
    48         case LUA_TTHREAD:{
    49             printf("LUA_TTHREAD
    ");
    50         }break;
    51 
    52         case LUA_NUMTAGS:{
    53             printf("LUA_NUMTAGS
    ");
    54         }break;
    55 
    56         default:{
    57             printf("%s
    ", lua_typename(L, t));
    58         }break;
    59         }
    60     }
    61 
    62     std::cout << "------ stack dump end ------" << std::endl;
    63 }

     

    Lua和C++交互系列:

    Lua和C++交互 学习记录之一:C++嵌入脚本

    Lua和C++交互 学习记录之二:栈操作

    Lua和C++交互 学习记录之三:全局值交互

    Lua和C++交互 学习记录之四:全局table交互

    Lua和C++交互 学习记录之五:全局数组交互

    Lua和C++交互 学习记录之六:全局函数交互

    Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块

    Lua和C++交互 学习记录之八:C++类注册为Lua模块

    Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

  • 相关阅读:
    redis乐观锁
    redis
    解决创建Redis容器没有conf配置文件
    redis缓存配置
    Docker架构
    Flask获取数据的一些方法
    Nginx正向代理、反向代理与负载均衡
    Sanic
    Dockerfile详解
    Centos7上安装docker
  • 原文地址:https://www.cnblogs.com/chevin/p/5885913.html
Copyright © 2011-2022 走看看