如何从C函数中回调Lua函数

我有一个 C 函数(A) test_callback,接受一个指向函数(B)的指针作为参数,并且 A 将会 "回调" B。

//typedef int(*data_callback_t)(int i);
int test_callback(data_callback_t f)
{
    f(3);
}

int datacallback(int a )
{
    printf("called back %d\n",a);
    return 0;
}

//example
test_callback(datacallback); // 输出: called back 3

现在,我想将 test_callback 包装起来,以便可以从 Lua 中调用它,假设名为 lua_test_callback;同时输入参数将会是一个 Lua 函数。我应该如何实现这个目标?

function lua_datacallback (a )
    print "hey , this is callback in lua" ..a
end

lua_test_callback(lua_datacallback)  //期望获得 "hey this is callback in lua 3 "

编辑:

这个链接 提供了一种将回调函数存储以供以后使用的方法。

//save function for later use
callback_function = luaL_ref(L,LUA_REGISTRYINDEX);

//retrive function and call it
lua_rawgeti(L,LUA_REGISTRYINDEX,callback_function);
//push the parameters and call it
lua_pushnumber(L, 5); // push first argument to the function
lua_pcall(L, 1, 0, 0); // 调用一个带有一个参数和没有返回值的函数

原文链接 https://stackoverflow.com/questions/2688040

点赞
stackoverflow用户169828
stackoverflow用户169828

我不确定我理解你的问题,如果你问的是 lua_test_callback 在C语言中会是什么样子,它应该是这样的:

int lua_test_callback(lua_State* lua)
{
    if (lua_gettop(lua) == 1 && // 确保只传递一个参数
       lua_isfunction(lua, -1)) // 并且该参数(在堆栈顶部)是函数
    {
        lua_pushnumber(lua, 3); // 将第一个参数压入函数
        lua_pcall(lua, 1, 0, 0); // 调用一个带有一个参数和没有返回值的函数
    }
    return 0; // 该函数不返回任何值
}

你不能直接封装 test_callback,你需要一个完全不同的实现来调用 Lua 函数。

(编辑:根据Nick的建议将lua_call改为lua_pcall。出于简洁起见,我仍然省略了任何错误处理)

2010-04-22 08:51:35
stackoverflow用户288406
stackoverflow用户288406

方便地调用具有不同签名的 Lua 函数的方法:

A. 创建一个能够安全维护 Lua 状态并提供简单接口的类。不要再反复地从头开始编写调用 Lua 函数的代码(包括大量 push/pop 操作和断言)——只需使用这个类接口即可。这是一种安全、快速、方便的方法。

B. 定义 push 和 pop 方法,在 Lua 堆栈上推入/弹出参数:

template<typename T> void push(T argument);
template<typename T> void get(const int index, T& return_value);

template<> void State::push(bool arg)
{
  lua_pushboolean (lua_state, arg ? 1 : 0);
}

template<> void State::push(float arg)
{
  lua_pushnumber (lua_state, arg);
}

template<> void State::push(int arg)
{
  lua_pushnumber (lua_state, arg);
}

// ...
template<> void State::get(const int index, bool& ret)
{
      if (!lua_isboolean(lua_state, index)) { ... }
      ret = lua_toboolean(lua_state, index) != 0;
}

C. 定义调用 Lua 函数的函数:

// 调用只带 1 个参数且无返回值的函数
template <typename A1>
void call(const char * funcName, A1 arg1)
{
  lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);       // 将全局函数 f 推入堆栈
  push (arg1);                                            // 将第一个参数推入堆栈
  assert_call(    lua_pcall(lua_state, 1, 0, this->err_h) );      // 调用带 1 个参数且无返回值的函数
}

// 调用带 2 个参数和 1 个返回值的函数
template <typename R1, typename A1, typename A2>
void callr1(const char * funcName, R1& res, A1 arg1, A2 arg2)
{
  lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);       // 将全局函数 f 推入堆栈
  push (arg1);                                            // 将第一个参数推入堆栈
  push (arg2);
  assert_call(    lua_pcall(lua_state, 2, 1, this->err_h) );      // 调用带 2 个参数和 1 个返回值的函数
  get  (-1, res);
  lua_pop(lua_state, 1);
}

D. 设置错误处理程序(lua_pcall 将调用此 Lua 函数来处理错误):

void setErrorHandler(const char * funcName)
{
  lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);
  this->err_h = lua_gettop(lua_state);
}
2010-04-22 18:00:45