From 8f88e104be42b84a61288c28710ab04ee17fb57d Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 29 Apr 2019 05:16:33 -0400 Subject: [PATCH] make sure that stack_aligned_stack_handler_function behaves properly --- .../stack_aligned_stack_handler_function.cpp | 45 +++++++++++++++++++ include/sol/protected_function.hpp | 12 ++--- include/sol/protected_handler.hpp | 6 ++- single/include/sol/forward.hpp | 4 +- single/include/sol/sol.hpp | 22 ++++----- 5 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 examples/source/stack_aligned_stack_handler_function.cpp diff --git a/examples/source/stack_aligned_stack_handler_function.cpp b/examples/source/stack_aligned_stack_handler_function.cpp new file mode 100644 index 00000000..b0f5ed42 --- /dev/null +++ b/examples/source/stack_aligned_stack_handler_function.cpp @@ -0,0 +1,45 @@ +#define SOL_CHECK_ARGUMENTS 1 +#include + +#include "assert.hpp" + +int main(int, char* []) { + sol::state lua; + lua.script("function func (a, b) return (a + b) * 2 end"); + + sol::reference func_ref = lua["func"]; + + // maybe this is in a lua_CFunction you bind, + // or maybe you're trying to work with a pre-existing system + // maybe you've used a custom lua_load call, or you're working + // with state_view's load(lua_Reader, ...) call... + // here's a little bit of how you can work with the stack + lua_State* L = lua.lua_state(); + + // this is a handler: + // stack_aligned_stack_handler, + // as its type name explains so verbosely, + // expects the handler on the stack + sol::stack_reference traceback_handler(L, -sol::stack::push(L, sol::default_traceback_error_handler)); + // then, you need the function + // to be on the stack + func_ref.push(); + sol::stack_aligned_stack_handler_function func(L, -1, traceback_handler); + lua_pushinteger(L, 5); // argument 1, using plain API + lua_pushinteger(L, 6); // argument 2 + + // take 2 arguments from the top, + // and use "stack_aligned_function" to call + int result = func(sol::stack_count(2)); + // function call pops function and arguments, + // leaves result on the stack for us + // but we must manually clean the traceback handler + // manually pop traceback handler + traceback_handler.pop(); + + // make sure everything is clean + c_assert(result == 22); + c_assert(lua.stack_top() == 0); // stack is empty/balanced + + return 0; +} diff --git a/include/sol/protected_function.hpp b/include/sol/protected_function.hpp index 6fff6106..bdb766bd 100644 --- a/include/sol/protected_function.hpp +++ b/include/sol/protected_function.hpp @@ -59,7 +59,7 @@ namespace sol { using base_t = basic_object; public: - typedef is_stack_based is_stack_handler; + using is_stack_handler = is_stack_based; static handler_t get_default_handler(lua_State* L) { return detail::get_default_handler::value>(L); @@ -105,9 +105,9 @@ namespace sol { try { #endif // Safe Exception Propagation #endif // No Exceptions - firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid()))); + firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid() && !is_stack_handler::value))); code = luacall(n, LUA_MULTRET, h); - poststacksize = lua_gettop(lua_state()) - static_cast(h.valid()); + poststacksize = lua_gettop(lua_state()) - static_cast(h.valid() && !is_stack_handler::value); returncount = poststacksize - (firstreturn - 1); #ifndef SOL_NO_EXCEPTIONS #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) @@ -305,7 +305,7 @@ namespace sol { template decltype(auto) call(Args&&... args) const { - if (!aligned) { + if constexpr (!aligned) { // we do not expect the function to already be on the stack: push it if (error_handler.valid()) { detail::protected_handler h(error_handler); @@ -326,12 +326,12 @@ namespace sol { // the handler will be pushed onto the stack manually, // since it's not already on the stack this means we need to push our own // function on the stack too and swap things to be in-place - if (!is_stack_handler::value) { + if constexpr (!is_stack_handler::value) { // so, we need to remove the function at the top and then dump the handler out ourselves base_t::push(); } detail::protected_handler h(error_handler); - if (!is_stack_handler::value) { + if constexpr (!is_stack_handler::value) { lua_replace(lua_state(), -3); h.stackindex = lua_absindex(lua_state(), -2); } diff --git a/include/sol/protected_handler.hpp b/include/sol/protected_handler.hpp index 26504181..e7eb2de3 100644 --- a/include/sol/protected_handler.hpp +++ b/include/sol/protected_handler.hpp @@ -67,8 +67,10 @@ namespace sol { } ~protected_handler() { - if (!is_stack::value && stackindex != 0) { - lua_remove(target.lua_state(), stackindex); + if constexpr (!is_stack::value) { + if (stackindex != 0) { + lua_remove(target.lua_state(), stackindex); + } } } }; diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index d4844925..822440d2 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-04-29 05:20:05.556326 UTC -// This header was generated with sol v3.0.1-beta2 (revision 67231f7) +// Generated 2019-04-29 09:16:12.925937 UTC +// This header was generated with sol v3.0.1-beta2 (revision c442c6c) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index caaaa25e..c1b51b07 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-04-29 05:20:05.284047 UTC -// This header was generated with sol v3.0.1-beta2 (revision 67231f7) +// Generated 2019-04-29 09:16:12.648677 UTC +// This header was generated with sol v3.0.1-beta2 (revision c442c6c) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -18153,8 +18153,10 @@ namespace sol { } ~protected_handler() { - if (!is_stack::value && stackindex != 0) { - lua_remove(target.lua_state(), stackindex); + if constexpr (!is_stack::value) { + if (stackindex != 0) { + lua_remove(target.lua_state(), stackindex); + } } } }; @@ -18219,7 +18221,7 @@ namespace sol { using base_t = basic_object; public: - typedef is_stack_based is_stack_handler; + using is_stack_handler = is_stack_based; static handler_t get_default_handler(lua_State* L) { return detail::get_default_handler::value>(L); @@ -18265,9 +18267,9 @@ namespace sol { try { #endif // Safe Exception Propagation #endif // No Exceptions - firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid()))); + firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid() && !is_stack_handler::value))); code = luacall(n, LUA_MULTRET, h); - poststacksize = lua_gettop(lua_state()) - static_cast(h.valid()); + poststacksize = lua_gettop(lua_state()) - static_cast(h.valid() && !is_stack_handler::value); returncount = poststacksize - (firstreturn - 1); #ifndef SOL_NO_EXCEPTIONS #if (!defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) || !SOL_NO_EXCEPTIONS_SAFE_PROPAGATION) || (defined(SOL_LUAJIT) && SOL_LUAJIT) @@ -18465,7 +18467,7 @@ namespace sol { template decltype(auto) call(Args&&... args) const { - if (!aligned) { + if constexpr (!aligned) { // we do not expect the function to already be on the stack: push it if (error_handler.valid()) { detail::protected_handler h(error_handler); @@ -18486,12 +18488,12 @@ namespace sol { // the handler will be pushed onto the stack manually, // since it's not already on the stack this means we need to push our own // function on the stack too and swap things to be in-place - if (!is_stack_handler::value) { + if constexpr (!is_stack_handler::value) { // so, we need to remove the function at the top and then dump the handler out ourselves base_t::push(); } detail::protected_handler h(error_handler); - if (!is_stack_handler::value) { + if constexpr (!is_stack_handler::value) { lua_replace(lua_state(), -3); h.stackindex = lua_absindex(lua_state(), -2); }