C模块回调Lua函数的两种方法

C模块回调Lua函数的两种方法

lua和C通过虚拟栈这种交互方式简单而又可靠,缺点就是C做栈平衡稍微会多写一点代码。 今天分享学到的C模块回调Lua函数的两种方法,都是炒冷饭,大侠勿喷。


1. C保存函数对象

C模块可以通过注册表保存Lua里面的对象,等适当时候取出再调用即可。

static int lua_callback = LUA_REFNIL;
 
static int setnotify(lua_State *L)
{
  lua_callback = luaL_ref(L, LUA_REGISTRYINDEX);
  return 0;
}
 
static int testnotify(lua_State *L)
{
  lua_rawgeti(L, LUA_REGISTRYINDEX, lua_callback);
  lua_call(L, 0, 0);
}


luaL_ref把栈顶的值取出,放到指定的tabel中,然后返回一个索引(目测是数组的index)。 lua_rawgeti把之前保存的function对象取出,再由lua_call调用。

function callback(  )
    print "Callback"
end
 
cb.setnotify(callback)
cb.testnotify()



2. C访问Lua全局环境

第二种方法更简便,C直接调用Lua中的函数,就像Lua调用C一样


static int testenv(lua_State *L)
{
  lua_getglobal(L, "defcallback");
  lua_call(L, 0, 0);
}


该方法的缺点就是如果C模块独立编写,方法名就不太灵活。 用这种方法一般会在Lua端再封装一层,以隔离全局环境。

3.例子


cb.c


#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
 
static int lua_callback = LUA_REFNIL;
 
static int setnotify(lua_State *L)
{
  lua_callback = luaL_ref(L, LUA_REGISTRYINDEX);
  return 0;
}
 
static int testnotify(lua_State *L)
{
  lua_rawgeti(L, LUA_REGISTRYINDEX, lua_callback);
  lua_call(L, 0, 0);
}
 
static int testenv(lua_State *L)
{
  lua_getglobal(L, "defcallback");
  lua_call(L, 0, 0);
}
 
static const luaL_Reg cblib[] = {
  {"setnotify", setnotify},
  {"testnotify", testnotify},
  {"testenv", testenv},
  {NULL, NULL}
};
 
int luaopen_cb(lua_State *L)
{
  luaL_register(L, "cb", cblib);
  return 1;
}


test.lua

require("cb")
 
function callback(  )
  print "Callback"
end
 
function defcallback()
  print "Predef callback"
end
 
cb.setnotify(callback)
cb.testnotify()
print "Done"
cb.testenv()




评论
您未登录,请您先 登录
annidy
积分 429
排名 2
关注 0
收藏 0
项目 1
文章 16
问题 3
回答 3
关注 主页 消息
文章激励
  • 文章激励期间起每编文章活动奖励积分5分
  • 原创文章奖励积分10分
  • 每月完成30编文章额外奖励积分30分
  • 成为平台博主将成为合作客户,获得博客页面所有收益权
  • 参与并完成活动即送虚拟主机或mysql资源一份
  • 2021-11-19 ~ 2022-3-1
文章汇总
最新文章
2016 - 2021 © srczh.com 版权所有 增值电信经营许可:粤ICP备19068081号
深圳市中文远星科技有限公司