Lua在C中分享了upvalue示例

时间:2017-09-03 09:23:16

标签: c lua closures global-variables

让我们为 Lua 5.3 创建一个简单的C模块,其中包含全局int

static int l_test(lua_State *L){
    int Global = lua_tointeger(L, lua_upvalueindex(1));
    Global++;
    lua_pushinteger(L, Global);
    lua_pushvalue(L, -1);
    lua_replace(L, lua_upvalueindex(1));
    //lua_pushnumber(L, Global);
    return 1;
}

static int l_anotherTest(lua_State *L){
    int Global = lua_tointeger(L, lua_upvalueindex(1));
    Global++;
    Global++;
    lua_pushinteger(L, Global);
    lua_pushvalue(L, -1);
    lua_replace(L, lua_upvalueindex(1));
    //lua_pushnumber(L, Global);
    return 1;
}

static const struct luaL_Reg testLib [] = {
    {"test", l_test},
    {"anotherTest", l_anotherTest},
    {NULL, NULL}
};

int luaopen_testLib(lua_State *L){
    luaL_newlibtable(L, testLib);
    lua_pushinteger(L, 1);
    luaL_setfuncs(L, testLib, 1) ;    
    return 1;
}

这几乎可行,但是当我从Lua这样调用这两个函数时:

local testLib = require "testLib"
print(testLib.test())
print(testLib.anotherTest())

第二次打印应为4,但会打印出3。 我还在做什么错?

1 个答案:

答案 0 :(得分:3)

不会共享C闭包的Upvalues,只有Lua闭包的upvalues。每个C闭包都直接包含其upvalues(参见here)。如果您想拥有两个或更多C闭包的共享值,请在所有C闭包中使用单个公用表作为upvalue,并将共享值放在那里,或者使用注册表代替共享数据。

以下内容应该符合您的要求:

#include <lua.h>
#include <lauxlib.h>


/* getint and setint may only be called from Lua C functions that
 * have the shared table as upvalue 1.
 */

static int getint(lua_State *L){
  int v = 0;
  lua_getfield(L, lua_upvalueindex(1), "myint");
  v = lua_tointeger(L, -1);
  lua_pop(L, 1); /* remove integer from stack */
  return v;
}

static void setint(lua_State *L, int v){
  lua_pushinteger(L, v);
  lua_setfield(L, lua_upvalueindex(1), "myint");
}


static int l_test(lua_State *L){
    int Global = getint(L);
    Global++;
    setint(L, Global);
    lua_pushinteger(L, Global);
    return 1;
}

static int l_anotherTest(lua_State *L){
    int Global = getint(L);
    Global++;
    Global++;
    setint(L, Global);
    lua_pushinteger(L, Global);
    return 1;
}

static const struct luaL_Reg testLib [] = {
    {"test", l_test},
    {"anotherTest", l_anotherTest},
    {NULL, NULL}
};

int luaopen_testLib(lua_State *L){
    luaL_newlibtable(L, testLib);
    lua_newtable(L);
    lua_pushinteger(L, 1);
    lua_setfield(L, -2, "myint");
    luaL_setfuncs(L, testLib, 1);
   return 1;
}