lua luaL_ref引用

介绍

int luaL_ref (lua_State *L, int t);
Creates and returns a reference, in the table at index t, for the object at the top of the stack (and pops the object)….
You can retrieve an object referred by reference r by calling lua_rawgeti(L, t, r). Function luaL_unref frees a reference and its associated object.
在当前栈索引t处的元素是一个table, 在该table中创建一个对象, 对象是当前栈顶的元素, 并返回创建对象在表中的索引值, 之后会pop栈顶的对象; (即将栈顶元素放到t对应的table中)

源码

freelist是值为0的宏, 所以可以任务总是将t的第0个值存放了下一个空闲位置的坐标;
空闲位置通过相互连接得到一个freelist: ref = t[freelist] 存放的是上一个之前被unref的元素的位置, 而 t[ref] 则是存放上上个unref的元素位置, 这样的连接方式就形成了freelist, 以便快速查找;

LUALIB_API int luaL_ref (lua_State *L, int t) {
  int ref;
  if (lua_isnil(L, -1)) {
    lua_pop(L, 1);  /* remove from stack */
    return LUA_REFNIL;  /* 'nil' has a unique fixed reference */
  }
  t = lua_absindex(L, t);
  lua_rawgeti(L, t, freelist);  /* get first free element   当前freelist保存了一个空闲元素位置 */
  ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist]   */    
  lua_pop(L, 1);  /* remove it from stack */
    //下面两步就是将当前freelist指向的ref位置的元素从freelist中删除, 
    //  同时将上上个被unref的元素位置放到freelist中;
    lua_rawgeti(L, t, ref);  /* remove it from list         t[ref] 存放的是上上个被unref的元素 */     
    lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
  }
  else  /* no free elements */
    ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
  lua_rawseti(L, t, ref);   // 将栈顶元素设置到t[ref]
  return ref;
}

下面看unref的函数源码:

LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
  if (ref >= 0) {
    t = lua_absindex(L, t);
    lua_rawgeti(L, t, freelist);
    lua_rawseti(L, t, ref);  /* t[ref] = t[freelist]   类似将unref的位置插入链表头 */   
    lua_pushinteger(L, ref);
    lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
  }
}

示例

可以用一个简单的例子来演示luaL_ref的用法:

// main.lua中有个全局函数
function gf()
  print("hello world")
end
// c++中处理
void callgf()
{
  lua_getglobal(L,"gf");
  // 存放函数到注册表中并返回引用
  int ref =  luaL_ref(L,LUA_REGISTRYINDEX);
  // 从注册表中读取该函数并调用
  lua_rawgeti(L,LUA_REGISTRYINDEX,ref);
  lua_pcall(L,0,0,0);
}

上面的函数会调用gf打印出”hello world”

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值