我有一个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 "
编辑:
This link提供了一种存储回调函数供以后使用的方法。
//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
答案 0 :(得分:9)
我不确定我理解你的问题,如果你问的是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函数。
(编辑:根据Nick的建议将lua_call
更改为lua_pcall
。为了简洁,我仍然省略了任何错误处理。
答案 1 :(得分:3)
使用不同签名调用不同Lua函数的便捷方式:
一个。创建一个能够安全维护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; }
℃。定义调用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); }