通过上一篇的热身,我们对C++调用lua变量有了一个认识,现在让我们再深入一点,去探索一下如何调用lua的函数、表。

Lua与宿主通讯的关键——栈

lua是个动态脚本语言,它的数据类型如何映射到C++这种静态类型语言中?lua是有GC机制的,这与C++手动管理内存相悖。如何解决这些问题呢?lua用一个抽象的栈与宿主语言交互,栈中的每一条记录都可以保存lua值。无论何时,我们想要从lua请求一个值,调用lua,被请求的值将会被压入栈。

栈是由lua来管理的,垃圾回收器知道哪个值正在被C使用(如果从lua中获得一个字符串char*时,我们需要自己备份一个,不然被lua回收后,我们保存的指针将会失效)。lua以一个严格的后进先出规则来操作栈,当我们调用lua时,它只会改变栈顶部分。我们的C代码有更多的自由,我们可以查询栈上的任何元素,甚至在任何一个地方插入和删除元素。

压栈API有如下:

查询栈中元素API:

其他的一些栈操作API:

 

调用lua函数

要调用一个函数,我们需要知道两个信息:函数的地址和函数的签名。如何获得lua中的指定函数的地址?很简单,与获得变量的地址一样,运用lua_getglobal(),第二个参数为lua函数的函数名。此时,该函数被压入栈顶了,如果存在的话。既然在栈顶了,那么我们可以使用lua_pcall()来调用栈顶的函数。代码如下:

 

运行之后,得到如下结果:

 

lua_pcall()这个API,我们之前已经接触过了,那是在读入文件、lua代码后,即luaL_load*()之后执行的操作。在这里,其后面的三个参数依然为0。后面三个参数到底有什么用呢?我们先来看一下lua文档:

lua_pcall()内部调用的是lua_call(),我们先来看看msgh这个参数,这个参数一般都设置为0,它只有在出错的时候才会有可能用到。我们的精力花在前两个参数上:nargs、nresults。

我来翻译一下:你必须遵守下面的协议来调用函数:首先,被调用的函数要被压入栈,该函数的参数要按照直接的顺序压入栈。第一个参数要第一个入栈,以此类推。最终你调用lua_call。nargs参数表示你压入栈中的参数个数。该函数及其所有的参数在被调用的时候都会从栈中弹出。函数的返回值将会在函数返回的时候压入栈中。返回值的个数用nresults这个参数来调整,除非传入的是LUA_MULTRET(注:即-1)。在这种情况下,函数的全部返回值都会入栈。lua会处理栈的空间,以使所有的返回值都有充足的栈空间。所有的返回值是以直接入栈的顺序压栈的(即第一返回值先入,依次类推),所以经过调用后,最后一个返回值在栈顶。

原来,nargs是表示传入参数个数,nresults指示返回参数个数。我们来写代码验证一下

我们在test.lua中定义了一个函数,该函数带有一个参数,两个返回值。我们先不管返回值,先关注其参数。根据说明,我们要先压入函数名,再压入参数。C++代码如下:

运行结果如下:

现在,我们来尝试获得返回值,根据lua函数的签名,我们指定两个返回值试试:

结果如下:

啊哈,是不是有种太简单了的感觉?你的感觉没错,就这么简单!根据文档,返回值的个数我们可以随意指定,如果感觉不过瘾,可以试试将返回值指定为1,-1,3。试试看有什么结果。

取得lua表数据

与调用lua函数不同的地方在于,这里我们使用lua的另一个API:lua_gettable()。我们先来看下文档:

 

翻译如下:将t[k]的值压入栈。t是栈中位于参数index所指向的位置,k为栈顶的值。此函数调用后,将会把栈顶的k的值出栈,将返回的结果放入栈顶。在lua中,这个调用将会触发metamethod的“index”事件。

根据描述,我们有如下代码:

 

结果如下:

至此,通过c++调用lua的各种数据的方式基本描述了一遍。接下来,我们要反客为主,用lua调用c++代码,这就有点纠结了,特别是调用c++ dll的时候。不过,u r lucky,我已经解决了问题,解决的方法已经在第一篇的代码中了。下一篇我我们一起来填坑。: )

总结

没啥总结。C++调用lua简单粗暴有用。值得一提的是,用sublime text写脚本,真是太舒服了!用它写lua、python爽快不止一点点。而且它还能用python扩展。强烈推荐大家写脚本的时候使用它。

C++与Lua交互(三)的更多相关文章

  1. C++与Lua交互之配置&交互原理&示例

    |Lua 简介 Lua 是一种轻量小巧的脚本语言,也是号称性能最高的脚本语言,它用C语言编写并以源代码形式开放. 某些程序常常需要修改内容,而修改的内容不仅仅是数据,更要修改很多函数的行为. 而修改函 ...

  2. C++与Lua交互(四)

    引言 通过前几篇,我们已经对Lua的C API有了一定的了解,如lua_push*.lua_is*.lua_to*等等.用C++调用Lua数据时,我们主要运用lua_getglobal与lua_pus ...

  3. C++与Lua交互(一)

    引言 之前做手游项目时,客户端用lua做脚本,基本所有游戏逻辑都用它完成,玩起来有点不爽,感觉"太重"了.而我又比较偏服务端这边(仅有C++),所以热情不高.最近,加入了一个端游项 ...

  4. lua视频教程三套高清新

    目录 1. 下载地址 2. 某网校 Lua 经典教程 3. lua脚本语言零基础开发教程19课全 4. LUA完整视频+Cocos2d-x项目实战 1. 下载地址 https://www.cnblog ...

  5. Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象

    话接上文.笔者为了方便使用Lua,自己编写了一个Lua的类.主要代码如下: QLua.h #ifndef QLUA_H #define QLUA_H // own #include "inc ...

  6. C++与Lua交互(二)

    上一篇我们搭建好了整个的项目环境,现在,我们一起探索一下如何将lua寄宿到C++中. 宿主的实现 我们在LuaWithCPPTest项目下,查看Source.cpp代码如下: #include < ...

  7. 最优雅的C++跟lua交互.

    我先来吐槽一下我们这个项目. 我是做手机游戏的, cocos2dx引擎, lua编码. 这本来是一件很欢快的事情, 因为不用接触C++. C++写久了的人写lua, 就会感觉任督二脉被打通了, 代码写 ...

  8. C++与lua交互

    项目开发的脚本层用的是Lua,引擎用的是C++.但是经理不给开放引擎层的代码.刚好最近项目空闲,安排了学习C++跟Lua的通信. 一.C++与Lua数据交互 数据交互主要是通过C API来实现 首先, ...

  9. 整理Lua和Unity和Lua交互文章链接

    重点文章: 1.[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(上) 2.[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(中) 3.Lua和C++交互详细总结 4. ...

随机推荐

  1. 使用Active MQ在.net和java系统之间通信

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现 一.特性列表 ⒈ 多种语言和 ...

  2. [Angular 2] Understanding OpaqueToken

    When using provider string tokens, there’s a chance they collide with other third-party tokens. Angu ...

  3. ios开发——实战Swift篇&简单项目的实现

    学了这么久的swift语法和相关技术,今天忍不住手痒痒就写了一个swift的小项目,这个项目非常简单(只是使用一个UITableView),但是里面的功能却非常有用. 我们要实现的功能是这样的: 程序 ...

  4. Python学习 之 数据类型(邹琪鲜 milo)

    1.Python中的数据类型:数字.字符串.列表.元组.字典 2.数字类型包括整型.长整型.浮点型.复数型 type(number):获取number的数据类型 整型(int):范围:-2,147,4 ...

  5. Qt for iOS,Qt 与Objective C混合编程

    项目设置 既然要聊 Qt 混合 OC 编程,首先要简单介绍一下 Objective C .我只有一句话:Go,问搜索引擎去.因为我所知实在有限,怕误导了您.当然如果您不怕,往下看吧. OC源文件介绍 ...

  6. jquery hasClass()、is() 多个

    一..hasClass() hasClass()方法是用来检查被选择的元素是否包含指定的class名,其语法: $(selector).hasClass("className"); ...

  7. Android基本控件之GridView

    我们在使用手机的过程中,会看到一些图片配上文字的一些情况,今天我们就来介绍一下安卓控件的GridView GridView组件用来以网格方式排列视图,与矩阵类似,当屏幕上有很多元素(文字.图片或其他元 ...

  8. 一网打尽OkHttp中的缓存问题

    看到很多小伙伴对OkHttp的缓存问题并不是十分了解,于是打算来说说这个问题.用好OkHttp中提供的缓存,可以帮助我们更好的使用Retrofit.Picasso等配合OkHttp使用的框架.OK,废 ...

  9. struts2.1笔记02:servlet简介

    1.     Servlet 是在服务器上运行的小程序.这个词是在 Java applet的环境中创造的,Java applet 是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果 ...

  10. [转]IIS7.5 添加expires头 提高性能

    本文转自:http://niutuku.com/tech/www/271454.shtml 对于页面中不经常变化的静态内容通过指定expires头,来进行浏览器端的缓存,减少每次访问时的请求. 原理: ...