2017-09-03 71 views
2
的upvalue例如

讓我們創建一個簡單的C模塊的Lua 5.3與全球intLua中共享使用C

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

要調用剛剛'setfuncs'之前初始化的upvalue,你應該推動其初始值壓入堆棧。要從'l_test'訪問upvalue,你應該使用'lua_upvalueindex(1)'來獲得這個值所在的棧pseudoindex。 –

+0

感謝您的提示。我已經更新了這個問題。這裏仍然缺少一些東西。你可以幫我嗎? – user1511417

+0

如果您想要一個空指針常量,則使用'NULL'宏。使用整數'0'是一個令人迷惑的遺產。 – Olaf

回答

3

C封閉價值不分攤,只有Lua封閉價值上漲。每個C閉包都直接包含其upvalues(請參閱here)。如果要爲兩個或更多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; 
} 
+0

@siffiejoe - 'luaL_setfuncs'允許您在所有註冊的C函數中共享upvalues。這是OP試圖實現的目標。 –

+2

@EgorSkriptunoff:來自luaL_setfuncs調用的所有C閉包在之後都具有相同的upvalues,但這些upvalues不是**共享的,即更改一個閉包的upvalues對其他閉包的upval沒有影響,*除了*如果你改變通過引用傳遞的值,比如表,用戶數據等(所有閉包都會對同一個表/ userdata/...有不同的引用)。 – siffiejoe

+1

我已經爲您挖出了一箇舊的郵件列表線程:http://lua-users.org/lists/lua-l/2006-08/msg00189.html – siffiejoe