I have a C function (A) test_callback
accepting a pointer to a function(B) as the parameter and A will \"callback\" B.
//typedef int(*data_callback
The convenient way of doing calls to different Lua functions with different signatures:
A. Make a class that will maintain Lua state safely and will provide easy interface. Do not write calls to Lua functions from scratch (with a lot of push/pop work and asserts) again and again - just use this class interface. This is safe, fast and convenient approach.
B. Define push and pop methods to push/pop arguments on/from Lua stack:
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. Define functions to call Lua functions:
// 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. Set error handler (lua_pcall will call this Lua function if error)
void setErrorHandler(const char * funcName) { lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); this->err_h = lua_gettop(lua_state); }
I'm not sure I understand your question, if you are asking what would lua_test_callback
look in C, it should be something like this
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
}
You cannot just wrap test_callback
, you need entirely different implementation to call Lua functions.
(edit: changed lua_call
to lua_pcall
as suggested by Nick. I still omitted any error handling for brevity)