我有一个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); // print : 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) //expect to get "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); // call a function with one argument and no return values
如果你问的是什么,我不确定我理解你的问题 lua_test_callback
看看C,它应该是这样的
int lua_test_callback(lua_State* lua)
{
if (lua_gettop(lua) == 1 && // make sure exactly one argument is passed
lua_isfunction(lua, -1)) // and that argument (which is on top of the stack) is a function
{
lua_pushnumber(lua, 3); // push first argument to the function
lua_pcall(lua, 1, 0, 0); // call a function with one argument and no return values
}
return 0; // no values are returned from this function
}
你不能只是包装 test_callback
,你需要完全不同的实现来调用Lua函数。
(编辑:改变了 lua_call
至 lua_pcall
正如尼克所说。为简洁起见,我仍然省略了任何错误处理)
如果你问的是什么,我不确定我理解你的问题 lua_test_callback
看看C,它应该是这样的
int lua_test_callback(lua_State* lua)
{
if (lua_gettop(lua) == 1 && // make sure exactly one argument is passed
lua_isfunction(lua, -1)) // and that argument (which is on top of the stack) is a function
{
lua_pushnumber(lua, 3); // push first argument to the function
lua_pcall(lua, 1, 0, 0); // call a function with one argument and no return values
}
return 0; // no values are returned from this function
}
你不能只是包装 test_callback
,你需要完全不同的实现来调用Lua函数。
(编辑:改变了 lua_call
至 lua_pcall
正如尼克所说。为简洁起见,我仍然省略了任何错误处理)
使用不同签名调用不同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函数的函数:
// Call function that takes 1 argument and returns nothing
template <typename A1>
void call(const char * funcName, A1 arg1)
{
lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); // push global function f on stack
push (arg1); // push first argument on stack
assert_call( lua_pcall(lua_state, 1, 0, this->err_h) ); // call function taking 1 argument and getting no return value
}
// call function that takes 2 argument and returns 1 value
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); // push global function f on stack
push (arg1); // push first argument on stack
push (arg2);
assert_call( lua_pcall(lua_state, 2, 1, this->err_h) ); // call function taking 2 arguments and getting 1 return value
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);
}