二、C/C++函数调用LUA函数
为应用程序注册新的C函数到Lua是扩展Lua的基本方法之一。一般本说,从Lua中调用C函数,不是指Lua可以调用任何类型的C函数。对于一个C函数来说,要调用Lua函数就必须遵循一些简单的协议来传递参数和获取返回结果。与此类似,从Lua中调用C函数,也必须遵循一些协议来传递参数和获得返回结果。具体来说,Lua和C上通过栈来交互的。特别注意的是,当Lua中调用C函数的时候,被调用的C函数总是获得一个新的LUA栈,这个栈不同于一般的栈以及C函数自己的栈。它包含最初的所有要传递给C函数的参数,也作为C函数将执行结果返回给调用者(LUA)的地方,即C函数push执行结果到栈上。为了方便,对这个栈的许多查询操作并不遵循严格的栈操作,相反,可以通过索引来访问栈上的任意元素。栈中的每个数据通过索引值进行定位,索引值为正时表示相对于栈底的偏移索引,索引值为负时表示相对于栈顶的偏移索引,索引值以1或-1为起始值,因此栈顶索引值永远为-1 ,栈底索引值永远为1 。
C函数调用Lua函数必须遵循的协议:首先,把被调用的LUA函数(地址)push到栈上;然后,将函数所需的所有参数按从左到右的顺序push到栈上,也就是说,第一个参数首先被push到栈;最后一步是调用lua_call(或者lua_pcall)。当LUA函数被调用,栈上所有的参数和函数地址都被从栈上弹出。
下面是一个C函数调用Lua函数的例子:
testluafunc.cpp的内容如下:
// …omitted…
lua_getglobal(L, "MyLuaAdd"); // push MyLuaAdd-fuction
lua_pushnumber(L, 10); // push first-argument
lua_pushnumber(L, 11); // push second-argument
lua_pcall(L, 2, 1, 0); // call MyLuaAdd-fuction
std::cout << "myadd(10, 11) == "
<< lua_tonumber(L, -1) // query result
<< std::endl;
lua_pop(L,1); // discard result from stack
// …omitted…
C函数调用Lua函数(全局变量)的过程:
(1) 将Lua函数(全局变量)入栈(eg. lua_getglobal(L, "MyLuaAdd"))
(2) 对于全局变量,直接通过lua_toXXX等函数直接从栈取出数据即可。而对于调用Lua函数,则按从左到右的顺序将各参数入栈。
(3) 指明参数个数以及返回值(以及错误处理),由lua_pcall或其它函数来调用LUA函数。
(4) 通过lua_toXXX等函数直接从栈取出LUA函数执行的结果即可。