欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-29 08:34:57
lua和c通过虚拟栈这种交互方式简单而又可靠,缺点就是c做栈平衡稍微会多写一点代码。 今天分享学到的c模块回调lua函数的两种方法,都是炒冷饭,大侠勿喷。 1. c保存函...

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()