From 51d6f6fa54274278aad8acba3b5efb65be847ca3 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 16 May 2017 06:12:28 -0400 Subject: [PATCH] You would think that we'd have accounted for this earlier... Fixes #405 --- examples/usertype_dynamic_getter_setter.cpp | 2 +- single/sol/sol.hpp | 17 +++-- sol/function_types.hpp | 13 +++- test_functions.cpp | 71 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/examples/usertype_dynamic_getter_setter.cpp b/examples/usertype_dynamic_getter_setter.cpp index 32b9ff81..c8b10499 100644 --- a/examples/usertype_dynamic_getter_setter.cpp +++ b/examples/usertype_dynamic_getter_setter.cpp @@ -61,7 +61,7 @@ struct vec { return sol::object(L, sol::in_place, sol::lua_nil); } - void setter(sol::stack_object key, sol::stack_object value, sol::this_state L) { + void setter(sol::stack_object key, sol::stack_object value, sol::this_state) { // we use stack_object for the arguments because we know // the values from Lua will remain on Lua's stack, // so long we we don't mess with it diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 4828c366..7f2d6432 100644 --- a/single/sol/sol.hpp +++ b/single/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 2017-05-15 14:41:13.667703 UTC -// This header was generated with sol v2.17.3 (revision 7eccb58) +// Generated 2017-05-16 10:11:15.504731 UTC +// This header was generated with sol v2.17.3 (revision 34b81be) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -9357,11 +9357,16 @@ namespace sol { stack::push(L, f); } - template + template >, std::is_base_of>>> = meta::enabler> static void select(lua_State* L, Fx&& fx, Args&&... args) { select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); } + template >, std::is_base_of>>> = meta::enabler> + static void select(lua_State* L, Fx&& fx) { + stack::push(L, std::forward(fx)); + } + template static void set_fx(lua_State* L, Args&&... args) { lua_CFunction freefunc = function_detail::call, 2>; @@ -9398,7 +9403,11 @@ namespace sol { template struct pusher> { - static int push(lua_State* L, std::function fx) { + static int push(lua_State* L, const std::function& fx) { + return pusher>{}.push(L, fx); + } + + static int push(lua_State* L, std::function&& fx) { return pusher>{}.push(L, std::move(fx)); } }; diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 91e4cea7..5bdf8ad5 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -190,11 +190,16 @@ namespace sol { stack::push(L, f); } - template + template >, std::is_base_of>>> = meta::enabler> static void select(lua_State* L, Fx&& fx, Args&&... args) { select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); } + template >, std::is_base_of>>> = meta::enabler> + static void select(lua_State* L, Fx&& fx) { + stack::push(L, std::forward(fx)); + } + template static void set_fx(lua_State* L, Args&&... args) { lua_CFunction freefunc = function_detail::call, 2>; @@ -231,7 +236,11 @@ namespace sol { template struct pusher> { - static int push(lua_State* L, std::function fx) { + static int push(lua_State* L, const std::function& fx) { + return pusher>{}.push(L, fx); + } + + static int push(lua_State* L, std::function&& fx) { return pusher>{}.push(L, std::move(fx)); } }; diff --git a/test_functions.cpp b/test_functions.cpp index dbf8efc3..a56d606b 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -1064,3 +1064,74 @@ TEST_CASE("functions/overloaded-variadic", "make sure variadics work to some deg REQUIRE(b == 3); REQUIRE(c == 2.2); } + +TEST_CASE("functions/set_function-already-wrapped", "setting a function returned from Lua code that is already wrapped into a sol::function or similar") { + SECTION("test different types") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::function fn = lua.script("return function() return 5 end"); + sol::protected_function pfn = fn; + std::function sfn = fn; + + lua.set_function("test", fn); + lua.set_function("test2", pfn); + lua.set_function("test3", sfn); + + REQUIRE_NOTHROW(lua.script("assert(type(test) == 'function')")); + REQUIRE_NOTHROW(lua.script("assert(test() ~= nil)")); + REQUIRE_NOTHROW(lua.script("assert(test() == 5)")); + + REQUIRE_NOTHROW(lua.script("assert(type(test2) == 'function')")); + REQUIRE_NOTHROW(lua.script("assert(test2() ~= nil)")); + REQUIRE_NOTHROW(lua.script("assert(test2() == 5)")); + + REQUIRE_NOTHROW(lua.script("assert(type(test3) == 'function')")); + REQUIRE_NOTHROW(lua.script("assert(test3() ~= nil)")); + REQUIRE_NOTHROW(lua.script("assert(test3() == 5)")); + } + + SECTION("getting the value from C++") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::function fn = lua.script("return function() return 5 end"); + + int result = fn(); + REQUIRE(result == 5); + } + + SECTION("setting the function directly") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::function fn = lua.script("return function() return 5 end"); + + lua.set_function("test", fn); + + REQUIRE_NOTHROW(lua.script("assert(type(test) == 'function')")); + REQUIRE_NOTHROW(lua.script("assert(test() ~= nil)")); + REQUIRE_NOTHROW(lua.script("assert(test() == 5)")); + + } + + SECTION("does the function actually get executed?") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + sol::function fn2 = lua.script("return function() print('this was executed') end"); + lua.set_function("test", fn2); + + REQUIRE_NOTHROW(lua.script("assert(type(test) == 'function')")); + REQUIRE_NOTHROW(lua.script("test()")); + } + + SECTION("setting the function indirectly, with the return value cast explicitly") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::function fn = lua.script("return function() return 5 end"); + + lua.set_function("test", [&fn]() { return fn.call(); }); + + REQUIRE_NOTHROW(lua.script("assert(type(test) == 'function')")); + REQUIRE_NOTHROW(lua.script("assert(test() ~= nil)")); + REQUIRE_NOTHROW(lua.script("assert(test() == 5)")); + } +}