Lua这个语言常常作为游戏引擎的游戏脚本,用于控制人物逻辑。一般Lua在游戏引擎中需要和其他语言进行沟通,而由于Lua是使用纯C写的语言,所以Lua当然也可以和C/C++沟通。
C++,Lua沟通的方式
C++和Lua沟通的方式其实是在内存中维护一个栈。需要注意的是:栈顶的index是-1,栈底的index是1:
也就是说,在这个图里你可以通过-3和5来指定同一个元素。
然后通过一些lua提供的API函数,Lua会将其变量,函数,表等放入栈中,然后C/C++再通过lua的API从栈中提取出来。同样C/C++也可以使用Lua的API将元素放入栈中供Lua使用。也就是说这个栈其实就是一个暂存,用于Lua和C/C++交流的通道。
C++调用Lua
头文件
首先需要知道要包含的头文件:
lua.hpp
这个头文件需要注意一下,如果你打开头文件,会发现里面是:
|
|
其实是包含了三个文件。那么如果你使用的是C语言,就直接包含这三个文件就可以了。
预备步骤
首先我们有如下的Lua文件:
|
|
首先我们需要初始化一个内存栈来作为交流中介:
|
|
使用luaL_newstate()
函数创建一个栈,栈的结构体就是lua_State*
。
然后需要将Lua文件和这个栈关联起来,不然怎么知道是和哪个Lua文件通信呢:
|
|
然后使用lua_pcall()
初始化栈(或者说将luafile中的信息记录出来):
|
|
以上就是预备步骤了。
获得数据
接下来需要获得数据。获得数据的方法是使用API让Lua把数据(变量)放入栈中,然后C/C++再获得:
|
|
首先使用lua_getglobal()
获得全局变量str
。这个时候Lua就会把变量str的值放入栈中了。接下来使用lua_isstring()
函数来判断栈顶元素是不是字符串(第二个参数是栈中元素的index,这里只有一个元素str所以直接在栈顶),如果是,则使用转换函数lua_tostring()
来返回这个变量(同样第二个参数也是index)。
需要注意的是:使用转换函数获得元素值之后是不能自动将这个元素从栈中删除的,想要删除需要使用void lua_remove (lua_State *L, int idx);
来移除idx上的值
也有其他的函数:
int lua_gettop (lua_State *L);
//返回栈顶索引(即栈长度)void lua_settop (lua_State *L, int idx);
//设置栈索引void lua_pushvalue (lua_State *L, int idx);
//将idx索引上的值的副本压入栈顶void lua_insert (lua_State *L, int idx);
//弹出栈顶元素,并插入索引idx位置void lua_replace (lua_State *L, int idx);
//弹出栈顶元素,并替换索引idx位置的值
获得表的操作有点麻烦,你需要首先使用lua_getglobal()
函数将表放到栈中,然后使用lua_getfield()
来将里面的字段放到栈中,然后再从栈里面获得字段值:
|
|
这里首先使用lua_getglobal()
将tbl放在栈顶,然后使用lua_getfield()
将tbl中的name属性入栈,再将id入栈,这样栈里面按顺序就是id, name, tbl
三个值。所以这里的lua_tostring()
作用在-2上。
调用函数
函数不能够直接通过转换函数,只能直接调用。 首先一样先让Lua将函数放到栈顶:
|
|
然后你需要将函数要用到的参数压入栈中:
|
|
然后使用函数lua_call();
来调用函数:
|
|
这个函数第二个参数是表示这个函数需要多少个参数,第三个参数是这个函数会返回多少个参数(Lua函数可以返回多参数)。然后Lua就会从栈里面获得参数和函数,然后调用,并且将返回值压入栈:
|
|
输出当然是2+7=9
。
Lua调用C++函数
想要在Lua中调用C/C++函数,我们可以首先将C/C++编译为链接库,然后在Lua中调用。(其实还有一种在C++代码中调用Lua,使用Lua调用C++代码的方法,但是好像没什么用,就不说了)
首先我们需要编写一个库:
|
|
然后要生成动态链接库mylib.so:
|
|
然后你就可以在Lua中使用这库了:
|
|