在c中保存状态

1. 注册表

注册表是一个普通的table,我们可以将c函数中需要保存的状态都存储在注册表中,注册表是可以被多个c模块共享的。

由于注册表是一个普通table,我们同样可以在栈中对其进行操作,只是这个table的索引是由一个常量LUA_REGISTRYINDEX进行索引。

如何向注册表中存入一个值对:

lua_pushstring(L, "hello");

lua_setfield(L, LUA_REGISTRYINDEX, "key");

lua_getfield(L, LUA_REGISTRYINDEX, "key");

如何向注册表中存入数组元素:

lua_pushstring(L, "i am a student");

int key = luaL_ref(L, LUA_REGISTRYINDEX); // 由于注册表的数组中已经存放了部分元素,因此不能使用自定义的索引,必须使用系统提供的函数,就无须关心索引的问题

                       // 成功调用后,会返回一个当前元素的索引

lua_rawgeti(L, LUA_REGISTRYINDEX, key);

 

2. upvalue:

upvalue机制提供了一种能和c函数关联起来的数据,upvalue可以保存一个lua值,然后可以将任意多的upvalue和c函数关联。在调用该c函数的时候,我们就可以提取和该函数关联的所有upvalue,这种技术又叫c closure。。即时用同一函数创建的closure,它们之间都是相互独立,即它们都拥有自己的upvalue。

 

如何创建一个c closure:

static int counter (lua_State* L) { // 同样我们需要创建我们的函数,和普通c函数一样

  int value = lua_tonumber(L, lua_upvalueindex(1)); // 提取第一个upvalue,这里有2个upvalue

  value *= 2;

  lua_pushnumber(L, value);

  return 1;

}

int newcounter (lua_State* L) { // 用于创建c closure的函数

  lua_pushnumber(L, 1);  // 将所有upvalue值都压入栈,这些值大多数情况是lua调用时候传入的参数

  lua_pushstring(L, "234");

  lua_pushcclosure(L, &counter, 2); // 创建c closure,c函数是counter,最后一个参数是2,代表从栈顶开始向下的2个值都作为c closure的upvalue

  return 1

}

实例:

c代码:

int t_tuple (lua_State* L) {
    int op = luaL_optint(L, 1, 0);
    if (op == 0) {
        int i;
        for (i = 1; !lua_isnone(L, lua_upvalueindex(i)); ++i) {
            lua_pushvalue(L, lua_upvalueindex(i));
        }
        return i - 1;
    }
    else {
        luaL_argcheck(L, op > 0, 1, "index out of range");
        if (lua_upvalueindex(op) == LUA_TNONE)
            return 0;
        else {
            lua_pushvalue(L, lua_upvalueindex(op));
            return 1;
        }
    }
}

int t_new (lua_State* L) {
    int top = lua_gettop(L);
    lua_pushcclosure(L, t_tuple, top);
    return 1;
}

lua代码:

local t = new (12, 2, "hello");
print(t())
print(t(2))
原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/5663527.html