From 0315a43b1b2dcc95724ec995a2253b2cbf0957c6 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 May 2014 19:58:47 -0400 Subject: [PATCH] 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" + ); +}