call_ret_t call(state_t &state, const function_ref_t &func, const Args &... args) { if( !func.is_valid() ) throw fatal_error_t(state, "lua function invalid()"); int top_beg = ::lua_gettop(state); func.get(); if( state != func.state() ) throw std::runtime_error("state not equal to function state"); std::int32_t arg_cnt = sizeof...( args ); push_value(state, args...); int error_index = 0; int base = ::lua_gettop(state) - arg_cnt; std::string error_msg; error_handler(state, error_msg); lua_insert(state, base); error_index = base; int error = lua_pcall(state, arg_cnt, LUA_MULTRET, error_index); if(error_index != 0) lua_remove(state, error_index); if( error != 0 ) throw fatal_error_t(state, error_msg, error); int top_last = ::lua_gettop(state); return call_ret_t(state, top_last - top_beg); }
call_ret_t call(state_t &state, const char *function_name, Args&&... args ) { assert(function_name && "function_name not be empty"); int top_beg = ::lua_gettop(state); ::lua_getglobal(state, function_name); std::int32_t arg_cnt = sizeof...(args); push_value(state, std::forward<Args>(args)...); int base = ::lua_gettop(state) - arg_cnt; std::string error_msg; error_handler(state, error_msg); lua_insert(state, base); int error_index = base; int error = lua_pcall(state, arg_cnt, LUA_MULTRET, error_index); if( error_index != 0 ) lua_remove(state, error_index); if( error != 0 ) throw fatal_error_t(state, error_msg, error); int top_last = ::lua_gettop(state); return call_ret_t(state, top_last - top_beg); }
inline void execute(state_t &state, const char *file_name) { assert(file_name); int top = ::lua_gettop(state); if( ::luaL_loadfile(state, file_name) ) throw fatal_error_t(state, ::lua_tostring(state, -1)); int error_index = 0; int base = ::lua_gettop(state); std::string error_msg; error_handler(state, error_msg); ::lua_insert(state, base); error_index = base; int error = ::lua_pcall(state, 0, LUA_MULTRET, error_index); if( error != 0 ) throw fatal_error_t(state, error_msg, error); }
static int handler(lua_State *state) { std::uint32_t len = 0; const char *msg = ::lua_tolstring(state, -1, &len); std::string error_msg; if( len == 0 ) error_msg = "unknown error"; else error_msg.append(msg, len); std::printf(error_msg.c_str()); std::printf("\n"); stack_trace(state, std::cerr); assert(0 && "lua has fatal error"); throw fatal_error_t(state_t(state), std::move(error_msg)); return 0; }