1. Lua与C通信,为什么使用虚拟的一个堆栈?

当在 Lua 和 C 之间交换数据有两个问题:

  • 动态与静态类型系统的不匹配
  • 自动与手动内存管理的不一致

Lua中a[k]=v,a和k可能的类型,有很多种,我们要想映射这个变量可能要写三个参数类型的每一种组合函数。(表、数字、字符串)

C中union 类型能来解决这个问题吗?

如此复杂的类型映射到其它语言可能很困难,

  • Lua 不仅被设计为与 C/C++易于交互, Java,Fortran 以及类似的语言也一样。
  • Lua负责垃圾回收:如果我们将 Lua 值保存在 C 变量中, Lua 引擎没有办法了解这种用法;它可能错误地认为某个值为垃圾并收集他。

所以,不能使用union关键字

替代的方案:

它用一个抽象的栈在 Lua 与 C 之间交换值。栈中的每一条记录都可以保存任何 Lua 值。


2.获取参数的过程:

无论你何时想要从 Lua 请求一个值(比如一个全局变量的值),调用 Lua,被请求的值将会被压入栈。无论你何时想要传递一个值给 Lua,首先将这个值压入栈,然后调用 Lua(这个值将被弹出)。 我们仍然需要一个不同的函数将每种 C 类型压入栈和一个不同函数从栈上取值(注:只是取出不是弹出),但是我们避免了多种不同类型参数的函数组合。

另外,因为栈是由 Lua 来管理的,垃圾回收器知道那个值正在被 C 使用。 几乎所有的 API函数都用到了栈。


3.Lua栈的规则:

Lua 以一个严格的 LIFO 规则(后进先出;也就是说,始终存取栈顶)来操作栈。
当你调用 Lua 时,它只会改变栈顶部分。你的C代码却有更多的自由;更明确的来讲,你可以查询栈上的任何元素,甚至是在任何一个位置插入和删除元素


4.压入元素

void lua_pushnil (lua_State *L);
void lua_pushboolean (lua_State *L, int bool);
void lua_pushnumber (lua_State *L, double n);
void lua_pushlstring (lua_State *L, const char *s,size_t length);//任意的字符串(char*类型,允许包含'\0'字符)用 lua_pushlstring,//C语言风格(以'\0'结束)的字符串( const char*)用 lua_pushstring:
void lua_pushstring (lua_State *L, const char *s);

Lua 中的字符串不是以零为结束符的;它们依赖于一个明确的长度,因此可以包含

任意的二进制数据。将字符串压入串的正式函数是lua_pushlstring,它要求一个明确的长度作为参数。

  • 对于以零结束的字符串,你可以用lua_pushstring(它用 strlen 来计算字符串长度)。
  • Lua 从来不保持一个指向外部字符串(或任何其它对象,除了 C 函数——它总
    是静态指针)的指针。
  • 对于它保持的所有字符串,Lua 要么做一份内部的拷贝要么重新利用已经存在的字符串。因此,一旦这些函数返回之后你可以自由的修改或是释放你的缓冲区。

5.查询元素

  • API 用索引来访问栈中的元素。在栈中的第一个元素(也就是第一个被压入栈的)
    有索引 1,下一个有索引2,以此类推。
  • 我们也可以用栈顶作为参照来存取元素,利用负索引。在这种情况下,-1 指出栈顶元素(也就是最后被压入的),-2 指出它的前一个元素,以此类推。
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_isuserdata)(lua_State *L,int idx);int lua_is... (lua_State *L, int index);//获取值int lua_toboolean (lua_State *L, int index);
double lua_tonumber (lua_State *L, int index);
const char * lua_tostring (lua_State *L, int index);
size_t lua_strlen (lua_State *L, int index);

Lua_tostring 函数返回一个指向字符串的内部拷贝的指针。你不能修改它(使你想起
那里有一个 const)。只要这个指针对应的值还在栈内, Lua 会保证这个指针一直有效。

当一个 C 函数返回后, Lua 会清理他的栈,所以,有一个原则:永远不要将指向 Lua 字符串的指针保存到访问他们的外部函数中。

Lua_string 返回的字符串结尾总会有一个字符结束标志 0, 但是字符串中间也可能包
含 0,lua_strlen 返回字符串的实际长度。特殊情况下,假定栈顶的值是一个字符串,下
面的断言(assert)总是有效的:

const char *s = lua_tostring(L, -1); /* any Lua string */
size_t l = lua_strlen(L, -1); /*its length */
assert(s[l] == '\0');
assert(strlen(s) <= l);

6.其他堆栈操作

除开上面所提及的 C 与堆栈交换值的函数外, API 也提供了下列函数来完成通常的堆栈维护工作:

//函数 lua_gettop 返回堆栈中的元素个数,它也是栈顶元素的索引。注意一个负数//索引-x 对应于正数索引 gettop-x+1。
int lua_gettop(lua_State *L);//lua_settop设置栈顶(也就是堆栈中的元素个数)为一个指定的值。如果开始的栈顶高于新的栈顶,顶部的值被丢弃。否则,为了得到指定的大小这个函数压入相应个数的空值//(nil)到栈上。特别的, lua_settop(L,0)清空堆栈。你也可以用负数索引作为调用 lua_settop 的参数;那将会设置栈顶到指定的索引。//利用这种技巧, API 提供了下面这个宏,它从堆栈中弹出 n 个元素:
//#definelua_pop(L,n) lua_settop(L, -(n)-1)void lua_settop(lua_State *L, int index);//函数 lua_pushvalue 压入堆栈上指定索引的一个抟贝到栈顶; lua_remove 移除指定索引位置的元素,并将其上面所有的元素下移来填补这个位置的空白;
void lua_pushvalue(lua_State *L, int index);
void lua_remove(lua_State *L, int index);
void lua_insert(lua_State *L, int index);
void lua_replace(lua_State *L, int index);

lua_insert移动栈顶元素到指定索引的位置,并将这个索引位置上面的元素全部上移至栈顶被移动留下的空隔;最后,lua_replace从栈顶弹出元素值并将其设置到指定索引位置,没有任何移动操作。

注意到下面的操作对堆栈没有任何影响:

lua_settop(L, -1); /* set top to its current value */
lua_insert(L, -1); /* move top element to the top */

demo:

static void stackDump (lua_State *L)
{int i;int top = lua_gettop(L);//从栈底到栈顶遍历了整个堆栈,依照每个元素自己的类型打印出其值。 for (i = 1; i <= top; i++) { /* repeat for each level */int t = lua_type(L, i);switch (t) {case LUA_TSTRING: /* strings */printf("`%s'", lua_tostring(L, i));break;case LUA_TBOOLEAN: /* booleans */printf(lua_toboolean(L, i) ? "true" : "false");break;case LUA_TNUMBER: /* numbers */printf("%g", lua_tonumber(L, i));break;default: /* other values */printf("%s", lua_typename(L, t));break;}printf(" "); /* put a separator */}printf("\n"); /* end the listing */
}int _tmain(int argc, _TCHAR* argv[])lua_State *L = lua_open();lua_pushboolean(L, 1); lua_pushnumber(L, 10);lua_pushnil(L); lua_pushstring(L, "hello");stackDump(L);/* true 10 nil `hello' */lua_pushvalue(L, -4); stackDump(L);/* true 10 nil `hello' true */lua_replace(L, 3); stackDump(L);/* true 10 true `hello' */lua_settop(L, 6); stackDump(L);/* true 10 true `hello' nil nil */lua_remove(L, -3); stackDump(L);/* true 10 true nil nil */lua_settop(L, -5); stackDump(L);/* true */lua_close(L);return 0;}

摘自 《Programming in Lua》,内容过多,适当进行了删减 ,加入自己的理解。

转载于:https://www.cnblogs.com/hiwoshixiaoyu/p/10034970.html

0基础lua学习(十八)C调用Lua----02Lua堆栈相关推荐

  1. WF4.0 基础篇 (二十八) WF调用PowerShell

    PowerShell 提供了命令行管理系统的功能,但通常情况下,操作人员要完成某种业务需要多组PowerShell 命令,这样会很烦琐,错误率也比效高.操作人员可以编写powerShell脚本来组织命 ...

  2. WF4.0 基础篇 (二十六) Interop调用WF3.X的Activity

    本节主要介绍Interop调用WF3.X的Activity 本文例子下载: http://files.cnblogs.com/foundation/InteropSample.rar 本文例子说明 I ...

  3. WF4.0 基础篇 (三十 完) 对学习WF的一点建议

    从09年10月份 NET4.0 Bata 2发布后,我就开始写[WF4.0 基础篇]这个系列,经历了5个多月终于在NET4.0正式发布前将这个系列完成了 这段时间与一些对WF4.0感兴趣的公司与开发人 ...

  4. PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization

    PyTorch框架学习十八--Layer Normalization.Instance Normalization.Group Normalization 一.为什么要标准化? 二.BN.LN.IN. ...

  5. Blender 3.0基础入门学习教程 Introduction to Blender 3.0

    成为Blender通才,通过这个基于项目的循序渐进课程学习所有主题的基础知识. 你会学到什么 教程获取:Blender 3.0基础入门学习教程 Introduction to Blender 3.0- ...

  6. android checkbox监听另一个checkbox选中和不选中_一个真正0基础小白学习前端开发的心路历程...

    摘要:真正的0基础小白学习前端开发的心路历程. 距离第一阶段的结束敲响了末尾的声音,抱着初心从开始8号的学习到第一阶段的结束这期间要应付期末考试应付自己的各种事情学习时间总是挤出来的这次学习让我受益匪 ...

  7. 15年大厂经历!大佬总结:0基础如何学习Python?

    在学习之前,你一定要知道你的学习目标是什么. 现在市面上有太多人鼓吹"Python太火了"."Python第一".但是,注意,"火".&qu ...

  8. 一个真正0基础小白学习前端开发的心路历程

    摘要:真正的0基础小白学习前端开发的心路历程. 距离第一阶段的结束敲响了末尾的声音,抱着初心从开始8号的学习到第一阶段的结束这期间要应付期末考试应付自己的各种事情学习时间总是挤出来的这次学习让我受益匪 ...

  9. 0基础怎么学习SEO?

    0基础怎么学习SEO?这是不少SEO初学者普遍存在的疑问,下面我们从一张图来看看SEO要怎么学?其实说实话,我本身接触SEO优化的时间也不久,与其说分享怎么学习,倒不如说怎么一起学习SEO优化. SE ...

  10. html5代码好学吗,0基础能学习Html5吗?Html5好学吗?

    原标题:0基础能学习Html5吗?Html5好学吗? 0基础可以学习Html5吗?这两年一直是被挂在嘴边的话题,随着人们对用户体验的要求越来越高,前端开发技术难度越来越大,所以对于IT从业者来讲,前端 ...

最新文章

  1. error C2733: 不允许重载函数的第二个 C 链接
  2. 第一百零四节,JavaScript时间与日期
  3. 软件设计开发笔记1:基于状态机的程序设计
  4. 扩展KMP模板(学习)
  5. JAVA毕业设计共享汽车管理系统计算机源码+lw文档+系统+调试部署+数据库
  6. 安全公司发现雄迈数字摄像机的主控口令“已泄露”
  7. 杨霖演讲实录∣从模块化架构到跨链生态,NULS这一年下了一盘怎么样的棋
  8. Word文档没保存电脑死机了,重启打开文档一片空白怎么办?
  9. 短线王的盯盘宝怎么样_股票盯盘系统app怎么样
  10. 2019最新升级【超能版】 vbox硬件级虚拟机系统 去虚拟化去vm标识 支持批量启动 批量克隆 CPA网赚挂机电商 virtualbox
  11. 3月18日 稠密光流FB,Deepflow,DIS,光流场的可视化
  12. 【优化充电】基于matlab遗传算法求解电动汽车充电统一管理优化问题(含负荷功率曲线对比图及充电计划)【含Matlab源码 2300期】
  13. NI无线通信与射频技术学习资源汇总
  14. 目标检测随笔1——目标检测简要综述
  15. CentOSnbsp;下mysqlnbsp;ERRORamp;n…
  16. Locating Restriction Sites
  17. 黑客入侵电脑?原来只需要简单几步就可以了
  18. 画论51 沈灏《画尘》
  19. 利用python爬虫大量基金股票的净值写入到csv文件中方便做其他计算
  20. html 怎么显示co2字体,检测空气中二氧化碳含量的三种方法

热门文章

  1. jni 从c传递map到java_java_jni 本地调用接口DLL的编写样本,涉及数组传递,相关的 和C程序均已包括。 Develop 256万源代码下载- www.pudn.com...
  2. MATLAB Primitive Types
  3. 卷积神经网络多输入和多输出
  4. 【java】监听器的使用
  5. 【java】矩阵的求解
  6. html行分割,如何确定一个html标签是否分割成多行
  7. linux启动关闭脚本,Linux中启动/停止/重启/状态的startup脚本
  8. _2020年10个最好的Linux发行版本
  9. matlab要求 基础,Matlab基础考试要求.doc
  10. java web相关试卷_JavaWeb试卷四