三、在LUA脚本中调用C/C++函数
可以被Lua函数调用的C函数必须遵循的协议(这个协议定义了参数和结果的传递方式):C函数从LUA栈上按直接的顺序获取参数(第一个参数首先被push)。所以当C函数开始执行时,lua_gettop(L)返回这个C函数的参数个数。第一个参数(如果有的话)索引为1,而最后一个参数的索引为lua_gettop(L)。为了将结果传递到LUA中,C函数将结果以直接的顺序push到栈上,并以结果的个数作为自己的返回值。栈上除结果以外的其它值将自动地被LUA以适当的方式删除掉。与LUA函数一样,被LUA调用的C函数也可能返回多个值到栈上。可以被Lua函数调用的C函数的类型:
typedef int (*lua_CFunction) (lua_State *L);
下面是一个Lua函数调用C函数的例子
TestCFunc.lua的内容如下:
function LuaCallMyCMax()
local tmp = MyCMax(10, 11, 12)
local str = "call MyCMax(10, 11, 12) in LUA and max number is "
print ( (str)..(tmp) )
return tmp
end
test.h的内容如下:
float max(float a, float b)
{
return (a>b ? a : b);
}
float max(float a, float b, float c)
{
float tmp = (a>b ? a : b);
return ( tmp>c ? tmp : c);
}
int _cdecl MyCMax(lua_State* L)
{
int n = lua_gettop(L); // number of arguments
int i;
for (i = 1; i <= n; i++) {
if (!lua_isnumber(L, i)) {
lua_pushstring(L, "incorrect argument");
lua_error(L);
}
}
lua_Number tmp = 0;
if (1 == n) {
tmp = lua_tonumber(L, 1);
} else if (2 == n) {
tmp = max(lua_tonumber(L, 1), lua_tonumber(L, 2));
}
else if (3 <= n) {
tmp = max(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3));
} else {
return 0;
}
lua_pushnumber(L, tmp); // first result
return 1; // number of results
}
test.cpp的内容如下:
// …omitted…
lua_pushcfunction(L, MyCMax); // push MyCMax -fuction
lua_setglobal(L, "MyCMax"); // registry MyCMax() as a global MyCMax in LUA
//或只一句lua_register(L, "MyCMax", MyCMax);
lua_getglobal(L, "LuaCallMyCMax");
lua_pcall(L, 0, 1, 0);
std::cout << "call LuaCallMyCMax() in C and result is "
<< lua_tonumber(L, -1)
<< std::endl;
lua_pop(L,1);
// …omitted…
Lua函数调用C函数的过程:
(1) 声明并定义一个类型为lua_CFunction的C函数 (eg. MyCMax)
(2) 将(1)定义的C函数(指针)入栈
(3) 调用LUA库的注册函数(eg. lua_setglobal宏) 以某name注册C函数
(4) 从LUA中以注册名name(eg. MyCMax,注册时可另取)调用C函数