C语言调用LUA匿名函数

这里我们考虑2种情况:

1)C语言调用LUA的命名函数

2)C语言调用LUA中的匿名函数(一般匿名函数作为C函数的入参传给C)

情况1网络上一搜一大把,这里主要介绍情况2。

首先,我们知道几种常识:

1)C与LUA通过虚拟栈实现通讯

2)LUA调用C函数,在C函数中,栈中的内容为函数的参数,匿名函数作为函数的入参,自然也在栈中。

3)C中调用LUA函数(命名or匿名),先将函数入栈,再将参数逐个入栈,然后调用lua_pcall执行函数,执行完成后,将函数与参数出栈,将返回值入栈。

 

好了,介绍到这里,想要在C中调用匿名函数,似乎很简单,只要以下步骤:

1)从栈中取出函数,放入栈顶(拷贝或移动皆可)

2)继续放入匿名函数的参数

3)执行函数调用

4)获取返回值

5)栈恢复(返回值出栈)

int lua_test3(lua_State *L)
{
    int num;
    int top;
    int ret;

    top = lua_gettop(L);
    printf("lua_test start: top = %d.\r\n", top);

    /* 入参为:num,func,num */
    /* 校验参数2是否是函数 */
    if (!lua_isfunction(L, 2)) {
        printf("LUA param 2 is not function!\r\n");
        return -1;
    }
    /* 将参数2拷贝一份到栈顶 */
    lua_pushvalue(L,2);
    /* 函数参数入栈 */
    lua_pushnumber(L, 999);

    top = lua_gettop(L);
    printf("lua_test before call: top = %d.\r\n", top);

    /* 执行函数 */
    ret= lua_pcall(L, 1, 1, 0);

    top = lua_gettop(L);
    printf("lua_test after call: top = %d.\r\n", top);

    /* 获取返回值,注意转换类型 */
    printf("callback result 1: %d!\r\n", (int)luaL_checknumber(L, -1));

    /* 返回值出栈 */
    lua_pop (L, 1);

    /* 本函数的返回值入栈 */
    lua_pushfstring(L, "%d", ret);

    top = lua_gettop(L);
    printf("lua_test end: top = %d.\r\n", top);

    /* 返回1个返回值 */
    return 1;
}

根据top的取值(栈的高度)我们可以看到,C函数参数会一直在栈底,假如我们要多次调用这个匿名函数,只要再次将匿名函数对象拷贝出来就可以了。假如我们在C函数中做很多复杂的操作,导致栈被清空了,这个时候匿名函数就不在栈里面了,怎么办?

可以把这个匿名函数保存起来!保存到LUA_REGISTRYINDEX注册表中,要用的时候再拿出来。

假设此时匿名函数变量已经在栈顶了,可以进行如下操作:

/* 将栈顶的匿名函数添加到表中 */
func_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
/* xxx:其他操作 */

/* 要用的时候,把该函数取出来,放入栈顶 */
lua_rawgeti(L, LUA_REGISTRYINDEX, func_ref_id);

/* 将参数入栈 */
lua_pushnumber(L, 888);

/* 调用函数 */
ret= lua_pcall(L, 1, 1, 0);

/* 返回值出栈 */
lua_pop (L, 1);

/* 解引用,如果这个函数不再需要了 */
luaL_unref(L, LUA_REGISTRYINDEX, func_ref_id);

最后,现在我也是刚入门LUA,上述文字是在网上搜索后,自己琢磨的,并经过程序验证。如有理解不对的地方,敬请指正!

你可能感兴趣的:(语言,LUA,匿名函数,C语言)