lua的closure创建和使用

    lua的闭包包括CClosure和FClosure两种类型。下面的例子介绍如何在C中使用C创建的闭包函数,C中使用lua中创建的闭包函数,Lua中使用C中创建的闭包函数,Lua中使用Lua闭包就不赘述了。

    C中通过lua_pushclosure创建闭包函数,在将闭包函数推到堆栈之前需要先把n个上值推到lua_state上。取用的时使用lua_upvalueindexn)取的特定索引上的上值,更改的话可以使用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 mytestlua_State *L) {
  //获取上值
  int upv = int)lua_tonumberL, lua_upvalueindex1));
  printf"%d
", upv);
  upv += 5;
  lua_pushintegerL, upv);
  lua_replaceL, lua_upvalueindex1));

  //获取一般参数
  printf"%d
", int)lua_tonumberL,1));

  return 0;
}

int mainvoid) {
  lua_State *L = luaL_newstate);
  luaL_openlibsL);

  //设置Cclosure函数的上值
  lua_pushintegerL,10);
  lua_pushintegerL,11);
  lua_pushcclosureL,mytest,2);
  lua_setglobalL,"upvalue_test");
  luaL_dofileL, "./luatest.lua");

  //获取fclosure上值的名称临时值, 不带env)
  lua_getglobalL, "l_counter");
  const char *name = lua_getupvalueL, -1, 1);
  printf"%s
", name);

  //设置fclosure上值
  lua_getglobalL, "l_counter");
  lua_pushintegerL,1000);
  name = lua_setupvalueL, -2, 1);
  printf"%s
", name);

  lua_getglobalL,"ltest");
  lua_pcallL,0,0,0);
  lua_getglobalL,"ltest");
  lua_pcallL,0,0,0);

  //获取fclosure的上值(带env)
  lua_getglobalL, "g_counter");
  lua_getupvalueL, -1, 1);
  
  //通过settable重新设置env中对应的值
  lua_pushstringL, "gloval_upvalue");
  lua_pushintegerL,10000);
  lua_settableL,-3);
  
  lua_pushstringL, "gloval_upvalue1");
  lua_pushintegerL,20000);
  lua_settableL,-3);
  
  lua_getglobalL,"gtest");
  lua_pcallL,0,0,0);
  lua_closeL);
  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)
  printg_testf))
end


function ltest)
  printl_testf))
end

upvalue_test1,2,3)
upvalue_test4,5,6)

  

Published by

风君子

独自遨游何稽首 揭天掀地慰生平