lua的closure創建和使用


    lua的閉包包括CClosure和FClosure兩種類型。下面的例子介紹如何在C中使用C創建的閉包函數,C中使用lua中創建的閉包函數,Lua中使用C中創建的閉包函數,Lua中使用Lua閉包就不贅述了。

    C中通過lua_pushclosure創建閉包函數,在將閉包函數推到堆棧之前需要先把n個上值推到lua_state上。取用的時使用lua_upvalueindex(n)取的特定索引上的上值,更改的話可以使用lua_replace更改上值。例子中每次將上值+5,因此在lua中每次調用upvalue_test函數都會獲得正確的上值。lua中的closure想在C中進行upvalue的更改有一點麻煩,首先你需要獲取closure函數對象,使用lua_getupvalue將特定索引上的上值放到棧頂,可以使用lua_setupvalue重設上值。如果你的fclosure中沒有使用全局變量,那么其上值索引應該是按照local變量的聲明順序來的,但是一旦使用了全局變量,第一個上值必定是_ENV環境,也就是說你可以通過重新設置_ENV環境,修改全局的上值,這也是修改環境變量的一種方法。

    C 文件:

#include <stdio.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <dlfcn.h>
#include <math.h>

static int mytest(lua_State *L) {
  //獲取上值
  int upv = (int)lua_tonumber(L, lua_upvalueindex(1));
  printf("%d\n", upv);
  upv += 5;
  lua_pushinteger(L, upv);
  lua_replace(L, lua_upvalueindex(1));

  //獲取一般參數
  printf("%d\n", (int)lua_tonumber(L,1));

  return 0;
}

int main(void) {
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  //設置Cclosure函數的上值
  lua_pushinteger(L,10);
  lua_pushinteger(L,11);
  lua_pushcclosure(L,mytest,2);
  lua_setglobal(L,"upvalue_test");
  luaL_dofile(L, "./luatest.lua");

  //獲取fclosure上值的名稱(臨時值, 不帶env)
  lua_getglobal(L, "l_counter");
  const char *name = lua_getupvalue(L, -1, 1);
  printf("%s\n", name);

  //設置fclosure上值
  lua_getglobal(L, "l_counter");
  lua_pushinteger(L,1000);
  name = lua_setupvalue(L, -2, 1);
  printf("%s\n", name);

  lua_getglobal(L,"ltest");
  lua_pcall(L,0,0,0);
  lua_getglobal(L,"ltest");
  lua_pcall(L,0,0,0);

  //獲取fclosure的上值(帶env)
  lua_getglobal(L, "g_counter");
  lua_getupvalue(L, -1, 1);
  
  //通過settable重新設置env中對應的值
  lua_pushstring(L, "gloval_upvalue");
  lua_pushinteger(L,10000);
  lua_settable(L,-3);
  
  lua_pushstring(L, "gloval_upvalue1");
  lua_pushinteger(L,20000);
  lua_settable(L,-3);
  
  lua_getglobal(L,"gtest");
  lua_pcall(L,0,0,0);
  lua_close(L);
  return 0;
}

  Lua 文件

     

gloval_upvalue = 10
gloval_upvalue1 = 20
local local_upvalue = 100

function l_counter()
   return function ()
      local_upvalue = local_upvalue + 1
      return local_upvalue
   end
end

function g_counter()
   return function ()
      gloval_upvalue = gloval_upvalue + 1
      return gloval_upvalue,gloval_upvalue1
   end
end

g_testf = g_counter()
l_testf = l_counter()

function gtest()
  print(g_testf())
end


function ltest()
  print(l_testf())
end

upvalue_test(1,2,3)
upvalue_test(4,5,6)

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM