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
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);
②stack -> c 判断栈里类型相关函数: lua_isxxx(lua_State *L, int idx)
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
LUA_API int (lua_isinteger) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
③stack -> c 获取栈里数据相关函数:lua_toxxx (lua_State *L, int idx)
LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_rawlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
3.Lua和栈之间的操作相关函数
①从Lua中得到数据放到栈里进行操作:lua_getxxx
LUA_API int (lua_getglobal) (lua_State *L, const char *name);
LUA_API int (lua_gettable) (lua_State *L, int idx);
LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawget) (lua_State *L, int idx);
LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API int (lua_getuservalue) (lua_State *L, int idx);
②从栈里将数据写入到Lua中:lua_setxxx
LUA_API void (lua_setglobal) (lua_State *L, const char *name);
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API void (lua_setuservalue) (lua_State *L, int idx);
4.基本的栈操作
//将一个可接受的索引 idx 转换为绝对索引 (即,一个不依赖栈顶在哪的值)
LUA_API int (lua_absindex)(lua_State *L, int idx); //取得栈中元素个数
LUA_API int (lua_gettop)(lua_State *L); //设置栈的大小为一个指定的值,而lua_settop(L,0)会把当前栈清空
//如果指定的index大于之前栈的大小,那么空余的空间会被nil填充
//如果index小于之前的栈中元素个数,则多余的元素会被丢弃
LUA_API void (lua_settop)(lua_State *L, int idx); //把栈中index所在位置的元素压入栈
LUA_API void (lua_pushvalue)(lua_State *L, int idx); //把从 idx 开始到栈顶的元素轮转 n 个位置。 对于 n 为正数时,轮转方向是
//向栈顶的; 当 n 为负数时,向栈底方向轮转 - n 个位置。 n 的绝对值不可
//以比参于轮转的切片长度大。
LUA_API void (lua_rotate)(lua_State *L, int idx, int n); //把fromidx处的元素copy一份插入到toidx,这操作不会修改fromidx处的元素
LUA_API void (lua_copy)(lua_State *L, int fromidx, int toidx); //确保堆栈上至少有 n 个额外空位。 如果不能把堆栈扩展到相应的尺寸,函
//数返回假。 失败的原因包括将把栈扩展到比固定最大尺寸还大 (至少是几
//千个元素)或分配内存失败。 这个函数永远不会缩小堆栈; 如果堆栈已经
//比需要的大了,那么就保持原样
LUA_API int (lua_checkstack)(lua_State *L, int n); //交换同一个状态机下不同线程中的值。
//这个函数会从 from 的栈上弹出n个值, 然后把它们压入to的栈上。
LUA_API void (lua_xmove)(lua_State *from, lua_State *to, int n);
5.一些有用的宏操作(方便操作,提供了一些宏)
//等价于调用 lua_tonumberx, 其参数 isnum 为 NULL。
#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) //等价于调用 lua_tointegerx, 其参数 isnum 为 NULL。
#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) //等价于调用 lua_tolstring , 其参数 len 为 NULL
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) //从栈中弹出 n 个元素。
#define lua_pop(L,n) lua_settop(L, -(n)-1) //创建一张空表,并将其压栈。 它等价于 lua_createtable(L, 0, 0)
#define lua_newtable(L) lua_createtable(L, 0, 0) //把 C 函数 f 设到lua的全局变量n 中
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) //将一个 C 函数压栈。 这个函数接收一个 C 函数指针, 并将一个类型为
//function 的 Lua 值压栈。 当这个栈顶的值被调用时,将触发对应的 C 函数。
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) //这个宏等价于 lua_pushlstring, 区别仅在于只能在 s 是一个字面量时才
//能用它。 它会自动给出字符串的长度。
#define lua_pushliteral(L, s) lua_pushstring(L, "" s) //将全局环境压栈。
#define lua_pushglobaltable(L) \
((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) //在栈的顶部的元素移动至index处
#define lua_insert(L,idx) lua_rotate(L, (idx), 1) //移除栈中index所在位置的元素
#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) //从栈顶弹出一个值,并把它设置到给定的index处
#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
6.为了调试方便,提供一个打印栈数据的函数方便使用
void stack_dump(lua_State* L){
printf("\n------ stack dump begin ------\n");
for (int i = ; i <= lua_gettop(L); ++i){
int t = lua_type(L, i);
switch (t){
case LUA_TNONE:{
printf("LUA_TNONE\n");
}break; case LUA_TNIL:{
printf("LUA_TNIL\n");
}break; case LUA_TBOOLEAN:{
printf("LUA_TBOOLEAN : %s\n", lua_toboolean(L, i) ? "true" : "false");
}break; case LUA_TLIGHTUSERDATA:{
printf("LUA_TLIGHTUSERDATA\n");
}break; case LUA_TNUMBER:{
//整形
if (lua_isinteger(L, i)){
printf("LUA_TNUMBER integer : %lld \n", lua_tointeger(L, i));
}
else if (lua_isnumber(L, i)){
printf("LUA_TNUMBER number: %g\n", lua_tonumber(L, i));
}
}break; case LUA_TSTRING:{
printf("LUA_TSTRING : %s\n", lua_tostring(L, i));
}break; case LUA_TTABLE:{
printf("LUA_TTABLE\n");
}break; case LUA_TFUNCTION:{
printf("LUA_TFUNCTION\n");
}break; case LUA_TUSERDATA:{
printf("LUA_TUSERDATA\n");
}break; case LUA_TTHREAD:{
printf("LUA_TTHREAD\n");
}break; case LUA_NUMTAGS:{
printf("LUA_NUMTAGS\n");
}break; default:{
printf("%s\n", lua_typename(L, t));
}break;
}
} std::cout << "------ stack dump end ------" << std::endl;
}
Lua和C++交互系列:
《Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块》
《Lua和C++交互 学习记录之八:C++类注册为Lua模块》
《Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类》
Lua和C++交互 学习记录之二:栈操作的更多相关文章
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...
- Lua和C++交互 学习记录之八:C++类注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之六:全局函数交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之五:全局数组交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之四:全局table交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之三:全局值交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之一:C++嵌入脚本
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- 我的hibernate学习记录(二)
通过上一篇文章我的hibernate学习记录(一)基本上的入门了hibernate,但是,里面还有还多东西是通过迷迷糊糊的记忆,或者说copy直接弄进去的,所以这篇文章就需要对上篇的一些文件.对象进行 ...
随机推荐
- Golang闭包入门了解
概念闭包就是一个函数与其相关的引用环境组成的一个整体.闭包本质其实是一个函数,但是这个函数会用到函数外的变量,它们共同组成的整体我们叫做闭包. 简单举例说明 package main import ( ...
- DOM EventListener
向元素添加事件句柄的语法:element.addEventListener(event, function, useCapture); 第一个参数是事件的类型,如click或者mousedown,注意 ...
- VIM自动补全Python代码
pydiction插件 https://codeload.github.com/rkulla/pydiction/zip/master 新建bundle文件夹 mkdir ~/.vim/bundle ...
- mint-ui之toast使用(messagebox,indicator同理)
toast为消息提示框,支持自定义位置.持续时间和样式. 一,注意事项 方法1 引入整个 Mint UI 组件,并需要再次单独引入Toast组件 Toast,它并不是一个全局变量,需要先引入 im ...
- linux /Android 平台下使用 i2c-tools
下载源码将 i2c-tools 代码下载到 Android 源码的 external 目录下 在 i2c-tools 目录下新建 Android.mk 文件,内容如下: # external/i2c- ...
- eclipse启动时发生的Initializing Java Tooling错误
eclipse在启动发生An internal error occurred during: "Initializing Java Tooling". java.lang.Null ...
- topcoder srm 683 div1
problem1 link 肯定存在相邻两堆满足不会存在任何操作在这两堆之间进行.然后就成为一条链,那么只需要维护链的前缀和即可判断当前堆和前一堆之间需要多少次操作. problem2 link 对于 ...
- ODAC(V9.5.15) 学习笔记(十)TVirtualTable
名称 类型 说明 Options TVirtualTableOptions 选择项,包括: voPersistentData:在数据集关闭时不处理其相关数据内容 voStored:设计期对数据集的处理 ...
- 第一次怎么把本地git仓库的内容push到远程仓库?
使用git push origin <分支名> -f 这种方式可以用本地仓库的内容覆盖远程仓库.
- SCU 4445 Right turn(dfs)题解
思路:离散化之后,直接模拟就行,标记vis开三维 代码: #include<iostream> #include<algorithm> #include<cstdio&g ...