前言#
上一篇文章讲了两个比较简单的api,今天我们来看两个稍微难理解的,也是实现lua和C++交互的,其中这两个api可能会涉及到事件的原方法,我们今天先引出来但是不做详细解释,在接下来的一章中将会给出例子,用来解释什么是元方法。
内容#
lua_getfield##
- 原型:void lua_getfield (lua_State *L, int index, const char *k);
- 解释:把 t[k] 值压入堆栈, 这里的 t 是指有效索引 index 指向的值。 在 Lua 中,这个函数可能触发对应 "index" 事件的元方法。
lua_setfield##
- 原型:void lua_setfield (lua_State *L, int index, const char *k);
- 解释:这个函数将把这个值弹出堆栈。 跟在 Lua 中一样,这个函数可能触发一个 "newindex" 事件的元方法。
Usage##
- 首先我们来编写一个lua文件,文件命名为fieldtest.lua,代码内容如下:
-- 变量系数
param =
{
a = 2;
b = 1;
}
-- 全局变量,满足c=2a+b,在c语言中实现
c = 100;
-- f(x) = ax + b
function lua_func(x)
return (param.a * x * x + param.b * x + c)
end
- 接下来我们来编写C语言函数,代码如下:
void print_stacknum(const char * desc, const int count)
{
printf("%s stack num = %d\n",desc, count);
}
void test_api_getfield()
{
lua_State *L = lua_open();
luaL_dofile(L,"fieldtest.lua"); // 加载执行lua文件
lua_getglobal(L,"param"); // 查找param变量压入栈底
print_stacknum("stage1", lua_gettop(L));
lua_getfield(L, -1, "a"); // 将Param.a入栈
int nParam_a = lua_tointeger(L,-1); // 将Param.a取出赋值给变量nParam_a
lua_getfield(L, -2, "b"); // 将Param.b入栈
int nParam_b = lua_tointeger(L,-1); // 将Param.b取出赋值给变量nParam_b
print_stacknum("stage2",lua_gettop(L));
lua_pop(L, 3); // 清除掉栈中多余的3个变量param、param.a、param.b
print_stacknum("stage3",lua_gettop(L));
int nParam_c = 2 * nParam_a + nParam_b;
lua_pushinteger(L, nParam_c); // 将c=2a+b计算完成,压入栈顶
lua_setfield(L, LUA_GLOBALSINDEX, "c");// 使用栈顶的值设置脚本全局变量c
print_stacknum("stage4",lua_gettop(L));
lua_getglobal(L,"lua_func"); // 查找lua_func函数压入栈底
lua_pushinteger(L, 3); // 压入函数变量x=3
lua_pcall(L,1,1,0); // 执行脚本函数lua_func
print_stacknum("stage5",lua_gettop(L));
int result = lua_tointeger(L,-1); // 从栈中取回返回值
lua_pop(L,1); // 弹出返回结果
print_stacknum("stage6",lua_gettop(L));
printf("\nresult = %d", result);
lua_close(L); //关闭lua环境
}
- 结果
总结#
- 注意例子中lua_getfield和lua_setfield方法的使用。
- 注意在程序过程中虚拟堆栈的变化情况,保持堆栈在函数执行前后不变是一个良好的习惯。
- 学会使用c来调用lua方法的写法。