Lua在C中的共享upvalue示例

Lua在C中的共享upvalue示例,c,lua,closures,global-variables,C,Lua,Closures,Global Variables,让我们使用全局int为Lua 5.3创建一个简单的C模块: 这几乎可以工作,但当我从Lua调用这两个函数时,如下所示: local testLib = require "testLib" print(testLib.test()) print(testLib.anotherTest()) 第二次打印应该是4,但它打印出的是3。 我还做错了什么?不共享C闭包的UPValue,只共享Lua闭包的UPValue。每个C闭包都包含其upvalue,请直接参阅。如果您想为两个或多个C闭包共享值,请在所有

让我们使用全局int为Lua 5.3创建一个简单的C模块:

这几乎可以工作,但当我从Lua调用这两个函数时,如下所示:

local testLib = require "testLib"
print(testLib.test())
print(testLib.anotherTest())
第二次打印应该是4,但它打印出的是3。
我还做错了什么?

不共享C闭包的UPValue,只共享Lua闭包的UPValue。每个C闭包都包含其upvalue,请直接参阅。如果您想为两个或多个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;
}

要初始化upvalue,应该在调用setfuncs之前将其初始值推送到堆栈上。要从l_测试中访问upvalue,您应该使用lua_upvalueindex1获取该值所在的堆栈伪索引。感谢您的提示。我已经更新了这个问题。这里还缺少一些东西。你能帮我吗?如果你想要一个空指针常量,请使用NULL宏。使用整数0是错误的。已更新,olaf。但这并没有让我们走得更远@siffiejoe-luaL_setfuncs允许您在所有注册的C函数之间共享upvalue。这就是OP试图达到的目的。@EgorSkriptunoff:luaL_setfuncs调用中的所有C闭包在调用后都将具有相同的UPValue,但这些UPValue不会共享,即更改一个闭包的UPValue不会影响其他闭包的UPValue,除非您对通过引用传递的值(如表、用户数据、,等等。所有闭包都将对同一个表/userdata/…有单独的引用。我为您找到了一个旧的邮件列表线程:@siffiejoe-thanking.@user1511417:the-2是相对堆栈索引,是lua_setfield调用的目标-1是堆栈顶部,在本例中是整数,因为它是最后一次推送的,而-2堆栈顶部下面的一个是在推送整数之前创建的表。
#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;
}