通过上一篇的热身,我们对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. TreeView1MouseMove

    procedure TForm1.TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,   Y: Integer); var   nod ...

  2. python 源码解读2

    http://www.jianshu.com/users/4d4a2f26740b/latest_articles http://blog.csdn.net/ssjhust123/article/ca ...

  3. 错误:expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token

    GCC编译C源程序时出现:错误:expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token,通常是因为在函数声明(包括包含的头文 ...

  4. Java_eclipse软件与git配合使用创建git仓库

    一.在eclipse上安装git,和安装其他插件一样 help->Install new software->add... 在弹出框中输入name,location;点击-->ok ...

  5. c#_错误处理_基础

    attribute: using System; using System.Collections.Generic; using System.Linq; using System.Web; usin ...

  6. Linux下*.tar.bz2等文件如何解压--转

    如果tar不支持j这个参数就先用 bzip2 -d xxx.tar.bz2 把它解压成.tar文件,然后再用 tar xvf xxx.tar 拆包.压缩解压 linux下怎么解后缀名是gzip的文件? ...

  7. VS 无法启动程序

    今天遇到这个问题网上找了很多资料,有很多人都遇到了这个问题,也有很多不同的答案,于是我们个答案都试了一遍都没有解决我这个问题的错误,于是就把控制面板中的打开功能和windows功能里面的Interne ...

  8. .NET平台数据持久层框架

    在.NET平台下的几个数据持久层框架: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS.NET 5.DAAB 6.DLinq

  9. MVC清除缓存设置+数据验证

    [OutputCache(Location = OutputCacheLocation.None, NoStore = true)] [Table("User")]:定义UserD ...

  10. MYSQL5.5和5.6参数的差异

    performance_schema 在 MySQL 5.6 中默认是开启的,但相关的很多参数相比 MySQL 5.5 却是降低了,例如 performance_schema 自动调整到 445 个表 ...