From 5d5ce9cd2e83c36cec34dd12c45461497e3f6e5e Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 15:30:14 -0400 Subject: [PATCH 1/6] `get` variant to easily get std::function from sol::function when using lua's call syntax. --- sol/function.hpp | 10 ++++++++++ sol/state.hpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sol/function.hpp b/sol/function.hpp index 5e6d0595..9da99ede 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -26,6 +26,7 @@ #include "tuple.hpp" #include "stack.hpp" #include +#include namespace sol { class function : public reference { @@ -79,6 +80,15 @@ public: return invoke(types(), sizeof...(Args)); } }; + +namespace stack { +namespace detail { + template + inline std::function get(types>, lua_State* L, int index = -1) { + return std::function(sol::function(L, index)); + } +} // detail +} // stack } // sol #endif // SOL_FUNCTION_HPP diff --git a/sol/state.hpp b/sol/state.hpp index 63f18713..b5470eb1 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -208,4 +208,4 @@ public: }; } // sol -#endif // SOL_STATE_HPP +#endif // SOL_STATE_HPP From fb1eb21f341080647748b1553bf028d55a0b1f3b Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 18:19:12 -0400 Subject: [PATCH 2/6] Additions for stack to properly handle std::function getters. std::function gets assume that the argument is a lua function and attempt to convert it to the type of function requested by the std::function's signature --- sol/function.hpp | 51 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 9da99ede..65ed135f 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -31,27 +31,27 @@ namespace sol { class function : public reference { private: - void luacall (std::size_t argcount, std::size_t resultcount) { + void luacall (std::size_t argcount, std::size_t resultcount) const { lua_call(state(), static_cast(argcount), static_cast(resultcount)); } template - std::tuple invoke(types, std::size_t n) { + std::tuple invoke(types, std::size_t n) const { luacall(n, sizeof...(Ret)); return stack::pop_reverse_call(state(), std::make_tuple, types()); } template - Ret invoke(types, std::size_t n) { + Ret invoke(types, std::size_t n) const { luacall(n, 1); return stack::pop(state()); } - void invoke(types, std::size_t n) { + void invoke(types, std::size_t n) const { luacall(n, 0); } - void invoke(types<>, std::size_t n) { + void invoke(types<>, std::size_t n) const { luacall(n, 0); } @@ -64,17 +64,17 @@ public: function& operator=(const function&) = default; template - void operator()(Args&&... args) { + void operator()(Args&&... args) const { call<>(std::forward(args)...); } template - typename return_type::type operator()(types, Args&&... args) { + typename return_type::type operator()(types, Args&&... args) const { return call(std::forward(args)...); } template - typename return_type::type call(Args&&... args) { + typename return_type::type call(Args&&... args) const { push(); stack::push_args(state(), std::forward(args)...); return invoke(types(), sizeof...(Args)); @@ -83,10 +83,37 @@ public: namespace stack { namespace detail { - template - inline std::function get(types>, lua_State* L, int index = -1) { - return std::function(sol::function(L, index)); - } +template +inline std::function get_std_func(types, types, lua_State* L, int index = -1) { + typedef typename function_traits::return_type return_t; + sol::function f(L, index); + auto fx = [ f, L, index ] (FxArgs&&... args) -> return_t { + return f(types(), std::forward(args)...); + }; + return std::move(fx); +} + +template +inline std::function get_std_func(types, types, lua_State* L, int index = -1) { + sol::function f(L, index); + auto fx = [ f, L, index ] (FxArgs&&... args) -> void { + f(std::forward(args)...); + }; + return std::move(fx); +} + +template +inline std::function get_std_func(types t, types<>, lua_State* L, int index = -1) { + return get_std_func(std::move(t), types(), L, index); +} + +template +inline std::function get(types>, lua_State* L, int index = -1) { + typedef typename function_traits fx_t; + typedef typename fx_t::args_type args_t; + typedef typename tuple_types::types_type ret_t; + return get_std_func(args_t(), ret_t(), L, index); +} } // detail } // stack } // sol From 61ecd1c87ebc33131a43e04935bdb8fbe4db4196 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 18:20:12 -0400 Subject: [PATCH 3/6] Bug with pop_call when concerning certain argument orders. Popping of the end of the stack was too dangerous, so instead we use a get call and pop all stack arguments off afterwards: helps to preserve order. --- sol/function_types.hpp | 56 ++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 3b5c4158..01b1325b 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -34,8 +34,10 @@ struct static_function { template static int typed_call(types, types t, function_type* fx, lua_State* L) { - stack::pop_call(L, fx, t); - return 0; + stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + return 0; } template @@ -46,8 +48,10 @@ struct static_function { template static int typed_call(types, types t, function_type* fx, lua_State* L) { typedef typename return_type::type return_type; - return_type r = stack::pop_call(L, fx, t); - stack::push(L, std::move(r)); + return_type r = stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -71,8 +75,10 @@ struct static_member_function { template static int typed_call(types, types, T& item, function_type& ifx, lua_State* L) { auto fx = [&item, &ifx](Args&&... args) -> void { (item.*ifx)(std::forward(args)...); }; - stack::pop_call(L, fx, types()); - return 0; + stack::get_call(L, fx, types()); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + return 0; } template @@ -84,8 +90,10 @@ struct static_member_function { static int typed_call(types, types, T& item, function_type& ifx, lua_State* L) { typedef typename return_type::type return_type; auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward(args)...); }; - return_type r = stack::pop_call(L, fx, types()); - stack::push(L, std::move(r)); + return_type r = stack::get_call(L, fx, types()); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -162,8 +170,10 @@ struct functor_function : public base_function { template int operator()(types, types t, lua_State* L) { - stack::pop_call(L, fx, t); - return 0; + stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + return 0; } template @@ -174,8 +184,10 @@ struct functor_function : public base_function { template int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; - return_type r = stack::pop_call(L, fx, t); - stack::push(L, r); + return_type r = stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + stack::push(L, r); return sizeof...(Ret); } @@ -206,7 +218,7 @@ struct member_function : public base_function { template int operator()(types, types t, lua_State* L) { - stack::pop_call(L, fx, t); + stack::get_call(L, fx, t); return 0; } @@ -218,8 +230,10 @@ struct member_function : public base_function { template int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; - return_type r = stack::pop_call(L, fx, t); - stack::push(L, std::move(r)); + return_type r = stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -258,8 +272,10 @@ struct userdata_function : public base_function { template int operator()(types, types t, lua_State* L) { - stack::pop_call(L, fx, t); - return 0; + stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + return 0; } template @@ -281,8 +297,10 @@ struct userdata_function : public base_function { template int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; - return_type r = stack::pop_call(L, fx, t); - // stack::push(L, std::move(r)); + return_type r = stack::get_call(L, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + // stack::push(L, std::move(r)); special_push(L, r); return sizeof...(Ret); } From 854d735410a9e7d9b7d7f272a03f74d995b1d877 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 18:21:19 -0400 Subject: [PATCH 4/6] Additional get_call argument that defaults index to 1 (first argument of stack). tuple_types had overlapping purpose: we should split it up soon --- sol/stack.hpp | 5 +++++ sol/tuple.hpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 4f8838c2..ae8f561f 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -298,6 +298,11 @@ inline auto get_call(lua_State* L, int index, TFx&& fx, types t) -> dec return detail::ltr_get(L, index, std::forward(fx), t, t); } +template +inline auto get_call(lua_State* L, TFx&& fx, types t) -> decltype(detail::ltr_get(L, 1, std::forward(fx), t, t)) { + return detail::ltr_get(L, 1, std::forward(fx), t, t); +} + template inline auto pop_call(lua_State* L, TFx&& fx, types t) -> decltype(detail::ltr_pop(L, std::forward(fx), t, t)) { return detail::ltr_pop(L, std::forward(fx), t, t); diff --git a/sol/tuple.hpp b/sol/tuple.hpp index d73783cb..d2b766bc 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -57,7 +57,7 @@ template struct build_reverse_indices<0, Ns...> : indices {}; template -struct types : build_indices { typedef types type; }; +struct types : build_indices { typedef types type; typedef types types_type; }; template struct reversed_ : Acc{}; @@ -81,4 +81,4 @@ const auto default_constructor = constructors>{}; } // sol -#endif // SOL_TUPLE_HPP +#endif // SOL_TUPLE_HPP From a842060e4d5e86693501981c4db4d725aae77c53 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 19:10:08 -0400 Subject: [PATCH 5/6] Removed std::true_type/false_type from tuple_types and created a separate is_tuple trait, so that we can use ::type on tuple_types without it interfering with base typedefs in std::true/false_type Fixing some identation Moved are_same type traits to traits.hpp --- sol/function.hpp | 2 +- sol/function_types.hpp | 38 +++++++++++++++++++------------------- sol/state.hpp | 8 +------- sol/traits.hpp | 14 +++++++++++++- sol/tuple.hpp | 6 +++--- sol/types.hpp | 2 +- tests.cpp | 28 ++++++++++++++++++++++++++++ 7 files changed, 66 insertions(+), 32 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 65ed135f..94c7a959 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -111,7 +111,7 @@ template inline std::function get(types>, lua_State* L, int index = -1) { typedef typename function_traits fx_t; typedef typename fx_t::args_type args_t; - typedef typename tuple_types::types_type ret_t; + typedef typename tuple_types::type ret_t; return get_std_func(args_t(), ret_t(), L, index); } } // detail diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 01b1325b..ffd62f90 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -35,9 +35,9 @@ struct static_function { template static int typed_call(types, types t, function_type* fx, lua_State* L) { stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - return 0; + return 0; } template @@ -49,9 +49,9 @@ struct static_function { static int typed_call(types, types t, function_type* fx, lua_State* L) { typedef typename return_type::type return_type; return_type r = stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - stack::push(L, std::move(r)); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -76,9 +76,9 @@ struct static_member_function { static int typed_call(types, types, T& item, function_type& ifx, lua_State* L) { auto fx = [&item, &ifx](Args&&... args) -> void { (item.*ifx)(std::forward(args)...); }; stack::get_call(L, fx, types()); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - return 0; + return 0; } template @@ -91,9 +91,9 @@ struct static_member_function { typedef typename return_type::type return_type; auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward(args)...); }; return_type r = stack::get_call(L, fx, types()); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - stack::push(L, std::move(r)); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -171,9 +171,9 @@ struct functor_function : public base_function { template int operator()(types, types t, lua_State* L) { stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - return 0; + return 0; } template @@ -185,9 +185,9 @@ struct functor_function : public base_function { int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; return_type r = stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - stack::push(L, r); + stack::push(L, r); return sizeof...(Ret); } @@ -231,9 +231,9 @@ struct member_function : public base_function { int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; return_type r = stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - stack::push(L, std::move(r)); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -273,9 +273,9 @@ struct userdata_function : public base_function { template int operator()(types, types t, lua_State* L) { stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - return 0; + return 0; } template @@ -297,10 +297,10 @@ struct userdata_function : public base_function { template int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; - return_type r = stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); + return_type r = stack::get_call(L, 2, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); lua_pop(L, nargs); - // stack::push(L, std::move(r)); + // stack::push(L, std::move(r)); special_push(L, r); return sizeof...(Ret); } diff --git a/sol/state.hpp b/sol/state.hpp index b5470eb1..5cf5630f 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -28,12 +28,6 @@ namespace sol { namespace detail { -template -struct are_same : std::true_type {}; - -template -struct are_same : std::integral_constant::value && are_same::value> {}; - inline int atpanic(lua_State* L) { std::string err = lua_tostring(L, -1); throw error(err); @@ -70,7 +64,7 @@ public: template void open_libraries(Args&&... args) { - static_assert(detail::are_same::value, "all types must be libraries"); + static_assert(are_same::value, "all types must be libraries"); if(sizeof...(args) == 0) { luaL_openlibs(L.get()); return; diff --git a/sol/traits.hpp b/sol/traits.hpp index 80f100b7..d87d2805 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -26,6 +26,12 @@ #include namespace sol { +template +struct are_same : std::true_type { }; + +template +struct are_same : std::integral_constant ::value && are_same::value> { }; + template using EnableIf = typename std::enable_if::type; @@ -53,6 +59,12 @@ struct return_type<> : types<>{ typedef void type; }; +template +struct is_tuple : std::false_type{ }; + +template +struct is_tuple> : std::true_type{ }; + template class Templ> struct is_specialization_of : std::false_type { }; template class Templ> @@ -147,4 +159,4 @@ struct function_traits { }; } // sol -#endif // SOL_TRAITS_HPP +#endif // SOL_TRAITS_HPP diff --git a/sol/tuple.hpp b/sol/tuple.hpp index d2b766bc..0b579397 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -57,7 +57,7 @@ template struct build_reverse_indices<0, Ns...> : indices {}; template -struct types : build_indices { typedef types type; typedef types types_type; }; +struct types : build_indices { typedef types type; }; template struct reversed_ : Acc{}; @@ -69,10 +69,10 @@ template struct reversed : reversed_, Args...>{}; template -struct tuple_types : types, std::false_type {}; +struct tuple_types : types {}; template -struct tuple_types> : types, std::true_type {}; +struct tuple_types> : types {}; template struct constructors {}; diff --git a/sol/types.hpp b/sol/types.hpp index 987f8ce7..348a17fd 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -160,4 +160,4 @@ inline bool operator==(nil_t, nil_t) { return true; } inline bool operator!=(nil_t, nil_t) { return false; } } // sol -#endif // SOL_TYPES_HPP +#endif // SOL_TYPES_HPP diff --git a/tests.cpp b/tests.cpp index c6ac269a..2e294c90 100644 --- a/tests.cpp +++ b/tests.cpp @@ -2,6 +2,15 @@ #include #include +void test_free_func( std::function f ) { + f( ); +} + +void test_free_func2( std::function f, int arg1 ) { + int val = f( arg1 ); + assert( arg1 == val ); +} + std::string free_function() { std::cout << "free_function()" << std::endl; return "test"; @@ -324,6 +333,25 @@ TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in t REQUIRE(tluaget == triple); } +TEST_CASE( "functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments" ) { + sol::state lua; + lua.open_libraries( sol::lib::base ); + + lua.set_function( "testFunc", test_free_func ); + lua.set_function( "testFunc2", test_free_func2 ); + lua.script( + "testFunc(function() print(\"hello std::function\") end)" + ); + lua.script( + "function m(a)\n" + " print(\"hello std::function with arg \", a)\n" + " return a\n" + "end\n" + "\n" + "testFunc2(m, 1)" + ); +} + TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { sol::state lua; lua.open_libraries(sol::lib::base); From 0315a43b1b2dcc95724ec995a2253b2cbf0957c6 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 19:58:47 -0400 Subject: [PATCH 6/6] Userdata-classes are now the assumed type for any unmatching `T` which are not derived from sol::reference or not one of the basic types tests added to confirm userdata can be passed into C++ function types demangle is now named lua_demangle, and the core demangle without any replacements (to fit lua) is just named demangle Formattings fixes everywhere --- sol/demangle.hpp | 34 +++++++++++++----------- sol/function_types.hpp | 27 ++++++++++--------- sol/stack.hpp | 13 +++++++--- sol/userdata.hpp | 2 +- tests.cpp | 59 ++++++++++++++++++++++++++++++++---------- 5 files changed, 88 insertions(+), 47 deletions(-) diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 09a32c29..b1ef893d 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -33,9 +33,26 @@ namespace sol { namespace detail { #ifdef _MSC_VER std::string demangle(const std::type_info& id) { + return id.name(); +} + +#elif defined(__GNUC__) || defined(__clang__) +std::string demangle(const std::type_info& id) { + int status; + char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); + std::string realname = unmangled; + free(unmangled); + return realname; +} + +#else +#error Compiler not supported for demangling +#endif // compilers + +std::string lua_demangle(const std::type_info& id) { + std::string realname = demangle(id); const static std::array removals = { "struct ", "class " }; const static std::array replacements = { "::", "_" }; - std::string realname = id.name(); for(std::size_t r = 0; r < removals.size(); ++r) { auto found = realname.find(removals[r]); while (found != std::string::npos) { @@ -52,20 +69,7 @@ std::string demangle(const std::type_info& id) { } return realname; } - -#elif defined(__GNUC__) || defined(__clang__) -std::string demangle(const std::type_info& id) { - int status; - char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); - std::string realname = unmangled; - free(unmangled); - return realname; -} - -#else -#error Compiler not supported for demangling -#endif // compilers } // detail } // sol -#endif // SOL_DEMANGLE_HPP +#endif // SOL_DEMANGLE_HPP diff --git a/sol/function_types.hpp b/sol/function_types.hpp index ffd62f90..0a90866c 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -270,20 +270,6 @@ struct userdata_function : public base_function { template userdata_function(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} - template - int operator()(types, types t, lua_State* L) { - stack::get_call(L, fx, t); - std::ptrdiff_t nargs = sizeof...(Args); - lua_pop(L, nargs); - return 0; - } - - template - int operator()(types<>, types t, lua_State* L) { - return (*this)(types(), t, L); - } - - template> typename std::enable_if::value, void>::type special_push(lua_State*, Return&&) { // push nothing @@ -294,6 +280,14 @@ struct userdata_function : public base_function { stack::push(L, std::forward(r)); } + template + int operator()(types, types t, lua_State* L) { + stack::get_call(L, 2, fx, t); + std::ptrdiff_t nargs = sizeof...(Args); + lua_pop(L, nargs); + return 0; + } + template int operator()(types, types t, lua_State* L) { typedef typename return_type::type return_type; @@ -305,6 +299,11 @@ struct userdata_function : public base_function { return sizeof...(Ret); } + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + virtual int operator()(lua_State* L) override { fx.prepare(L); return (*this)(tuple_types(), typename traits_type::args_type(), L); diff --git a/sol/stack.hpp b/sol/stack.hpp index ae8f561f..4d004e00 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -61,16 +61,21 @@ inline type get(types, lua_State* L, int index = -1) { return static_cast(lua_type(L, index)); } +template ::type> +inline U get_sol_type(std::true_type, types, lua_State* L, int index = -1) { + return U(L, index); +} + template -inline T& get(types>, lua_State* L, int index = -1) { +inline T& get_sol_type(std::false_type, types, lua_State* L, int index = -1) { userdata_t udata = get(types{}, L, index); T* obj = static_cast(udata.value); return *obj; } -template ::type> -inline U get(types, lua_State* L, int index = -1) { - return U(L, index); +template > +inline auto get(types t, lua_State* L, int index = -1) -> decltype(get_sol_type(std::is_base_of(), t, L, index)) { + return get_sol_type(std::is_base_of(), t, L, index); } template diff --git a/sol/userdata.hpp b/sol/userdata.hpp index d6c8af02..07dc262b 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -42,7 +42,7 @@ struct userdata_traits { }; template -const std::string userdata_traits::name = detail::demangle(typeid(T)); +const std::string userdata_traits::name = detail::lua_demangle(typeid(T)); template const std::string userdata_traits::metatable = std::string("sol.stateful.").append(name); diff --git a/tests.cpp b/tests.cpp index 2e294c90..f415721e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -2,13 +2,13 @@ #include #include -void test_free_func( std::function f ) { - f( ); +void test_free_func(std::function f) { + f(); } -void test_free_func2( std::function f, int arg1 ) { - int val = f( arg1 ); - assert( arg1 == val ); +void test_free_func2(std::function f, int arg1) { + int val = f(arg1); + assert(arg1 == val); } std::string free_function() { @@ -16,6 +16,25 @@ std::string free_function() { return "test"; } +struct self_test { + int bark; + + self_test() : bark(100) { + + } + + void g(const std::string& str) { + std::cout << str << '\n'; + bark += 1; + } + + void f(const self_test& t) { + std::cout << "got test" << '\n'; + assert(t.bark == bark); + assert(&t == this); + } +}; + struct object { std::string operator() () { std::cout << "member_test()" << std::endl; @@ -284,7 +303,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work std::cout << "stateless lambda()" << std::endl; return "test"; } - ); +); REQUIRE_NOTHROW(run_script(lua)); lua.get("os").set_function("fun", &free_function); @@ -302,7 +321,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work std::cout << "stateless lambda()" << std::endl; return "test"; } - ); +); REQUIRE_NOTHROW(run_script(lua)); // r-value, cannot optimise @@ -333,15 +352,15 @@ TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in t REQUIRE(tluaget == triple); } -TEST_CASE( "functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments" ) { +TEST_CASE("functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments") { sol::state lua; - lua.open_libraries( sol::lib::base ); + lua.open_libraries(sol::lib::base); - lua.set_function( "testFunc", test_free_func ); - lua.set_function( "testFunc2", test_free_func2 ); + lua.set_function("testFunc", test_free_func); + lua.set_function("testFunc2", test_free_func2); lua.script( "testFunc(function() print(\"hello std::function\") end)" - ); + ); lua.script( "function m(a)\n" " print(\"hello std::function with arg \", a)\n" @@ -349,7 +368,7 @@ TEST_CASE( "functions/sol::function to std::function", "check if conversion to s "end\n" "\n" "testFunc2(m, 1)" - ); + ); } TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { @@ -521,3 +540,17 @@ TEST_CASE("tables/userdata utility derived", "userdata classes must play nice wh REQUIRE((lua.get("dgn10") == 70)); REQUIRE((lua.get("dgn") == 7)); } + + +TEST_CASE("tables/self-referential userdata", "userdata classes must play nice when C++ object types are requested for C++ code") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_userdata("test", "g", &self_test::g, "f", &self_test::f); + + lua.script( + "local a = test.new()\n" + "a:g(\"woof\")\n" + "a:f(a)\n" + ); +}