From 9328271d06c4dd7bd862c841a1a12a1d3f1de748 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 24 Apr 2014 23:38:32 -0400 Subject: [PATCH 1/8] Renames for lua_function's internal types and some early-caught fixes for using the right type for the member of the function Preparation for dumping whole classes into lua... it's going to be fairly tough making this one work. --- sol/lua_function.hpp | 62 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index f2ddae0b..a294db0c 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -175,7 +175,7 @@ template struct functor_lua_func : public lua_func { typedef decltype(&TFx::operator()) fx_t; typedef function_traits fx_traits; - TFx fx; + fx_t fx; template functor_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} @@ -208,7 +208,7 @@ template::type>::type fx_t; typedef function_traits fx_traits; - TFx fx; + fx_t fx; template function_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} @@ -241,12 +241,12 @@ template struct function_lua_func : public lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; - struct lambda { + struct functor { T member; - TFx invocation; + fx_t invocation; template - lambda(T m, FxArgs&&... fxargs): member(std::move(m)), invocation(std::forward(fxargs)...) {} + functor(T m, FxArgs&&... fxargs): member(std::move(m)), invocation(std::forward(fxargs)...) {} template typename fx_traits::return_type operator()(Args&&... args) { @@ -281,6 +281,58 @@ struct function_lua_func : public lua_func { } }; +template +struct class_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type fx_t; + typedef function_traits fx_traits; + struct functor { + T& member; + fx_t invocation; + + template + functor(FxArgs&&... fxargs): member(*static_cast(nullptr)), invocation(std::forward(fxargs)...) {} + + void pre_call( lua_State* L ) { + void* userdata = lua_touserdata( L, 0 ); + T* item = static_cast( userdata ); + member = *item; + } + + template + typename fx_traits::return_type operator()(Args&&... args) { + return (member.*invocation)(std::forward(args)...); + } + } fx; + + template + class_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} + + template + int operator()(types, types t, lua_State* L) { + fx.pre_call(L); + stack::pop_call(L, fx, t); + return 0; + } + + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + + template + int operator()(types, types t, lua_State* L) { + typedef typename multi_return::type return_type; + fx.pre_call(L); + return_type r = stack::pop_call(L, fx, t); + stack::push(L, std::move(r)); + return sizeof...(Ret); + } + + virtual int operator()(lua_State* L) override { + return (*this)(tuple_types(), typename fx_traits::args_type(), L); + } +}; + } // sol #endif // SOL_LUA_FUNC_HPP From c145759da87f0ee1894c46f07f1cab4c9853c814 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 25 Apr 2014 00:05:42 -0400 Subject: [PATCH 2/8] Deprecation mechanism, improvements to lua_function's classes, and demangling for MSVC and gcc/clang --- sol/demangle.hpp | 68 ++++++++++++++++++++++++++++++++++++++++++++ sol/deprecate.hpp | 35 +++++++++++++++++++++++ sol/lua_function.hpp | 4 +-- 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 sol/demangle.hpp create mode 100644 sol/deprecate.hpp diff --git a/sol/demangle.hpp b/sol/demangle.hpp new file mode 100644 index 00000000..9328673b --- /dev/null +++ b/sol/demangle.hpp @@ -0,0 +1,68 @@ +// The MIT License (MIT) + +// Copyright (c) 2013 Danny Y., Rapptz + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_DEMANGLE_HPP +#define SOL_DEMANGLE_HPP + +#include + +#ifdef _MSC_VER +#include +#include + +namespace sol { +namespace detail { + + + std::string demangle(const std::type_info& id) { + std::string realname(2048, '\0'); + DWORD result = UnDecorateSymbolName(id.raw_name(), realname.data(), realname.size(), UNDNAME_32_BIT_DECODE); + if (result == 0) + return ""; + realname.resize(result); + return realname; + } + +#elif __GNUC__ || __clang__ +#include + +namespace sol { +namespace detail { + + 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 +namespace sol { +namespace detail { + +#error Implement demangling for this platform +#endif // VC++ || GCC || Others + +} // detail +} // sol + +#endif // SOL_DEMANGLE_HPP \ No newline at end of file diff --git a/sol/deprecate.hpp b/sol/deprecate.hpp new file mode 100644 index 00000000..bd14b5c1 --- /dev/null +++ b/sol/deprecate.hpp @@ -0,0 +1,35 @@ +// The MIT License (MIT) + +// Copyright (c) 2013 Danny Y., Rapptz + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_DEPRECATE_HPP +#define SOL_DEPRECATE_HPP + +#ifndef DEPRECATE +#ifdef _MSC_VER +#define DEPRECATE __declspec(deprecated) +#elif __GNUC__ +#define DEPRECATE __attribute__((deprecated)) +#else +#define DEPRECATE [[deprecated]] +#endif // VC++ || GCC || Others +#endif // DEPRECATE + +#endif // SOL_DEPRECATE_HPP \ No newline at end of file diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index a294db0c..5110e0e3 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -97,12 +97,12 @@ struct static_lua_func { template struct static_object_lua_func { - typedef typename std::decay::type fx_t; + typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; template static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { - auto fx = [&item, &ifx](Args&&... args) { (item.*ifx)(std::forward(args)...); }; + auto fx = [&item, &ifx](Args&&... args) -> void { (item.*ifx)(std::forward(args)...); }; stack::pop_call(L, fx, types()); return 0; } From 359848f371155f30bb93af8845638bb1b723178f Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 25 Apr 2014 09:25:08 -0400 Subject: [PATCH 3/8] Demangler is alive, it seems. But honestly, MSVC is kind of crappy about it: perhaps, later, we'll just take a string indicating the name of the class. main.cpp contains the test implementation for the lua classes -- woo! --- main.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++ sol/demangle.hpp | 21 +++++++-- 2 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 main.cpp diff --git a/main.cpp b/main.cpp new file mode 100644 index 00000000..0532dee1 --- /dev/null +++ b/main.cpp @@ -0,0 +1,118 @@ +#include +#include + +namespace sol { + + template + struct constructors; + + template + class lua_class { + public: + static const std::string classname; + static const std::string meta; + + private: + std::string luaname; + std::vector functionnames; + std::vector functions; + std::vector functiontable; + std::vector metatable; + + struct maker { + + static int construct( lua_State* L ) { + // First argument is now a table that represent the class to instantiate + luaL_checktype( L, 1, LUA_TTABLE ); + + lua_newtable( L ); // Create table to represent instance + + // Set first argument of new to metatable of instance + lua_pushvalue( L, 1 ); + lua_setmetatable( L, -2 ); + + // Do function lookups in metatable + lua_pushvalue( L, 1 ); + lua_setfield( L, 1, "__index" ); + + void* userdata = lua_newuserdata( L, sizeof( T ) ); + T* obj = static_cast( userdata ); + std::allocator alloc{ }; + alloc.construct( obj ); + } + + template + static int destruct( lua_State* L ) { + void* userdata = lua_touserdata( L, 0 ); + T* obj = static_cast( userdata ); + std::allocator alloc{ }; + alloc.destroy( obj ); + } + }; + + void build_function_tables( ) { + + } + + template + void build_function_tables( Ret( T::* func )( MArgs... ), std::string name, Args&&... args ) { + functionnames.push_back( std::move( name ) ); + functions.emplace_back( std::move( func ) ); + functiontable.push_back( { functionnames.back().c_str(), &lua_func::call } ); + build_function_tables( std::forward( args )... ); + } + + public: + template + lua_class( Args&&... args ) : lua_class( classname, std::forward( args )... ) { + + } + + template + lua_class( std::string name, Args&&... args ) : lua_class( name, constructors<>(), std::forward( args )... ) { + + } + + template + lua_class( std::string name, constructors c, Args&&... args ) : luaname( std::move( name ) ) { + functionnames.reserve( sizeof...( args ) ); + functiontable.reserve( sizeof...( args ) ); + metatable.reserve( sizeof...( args ) ); + build_function_tables( std::forward( args )... ); + functiontable. + } + }; + + template + const std::string lua_class::classname = detail::demangle( typeid( T ) ); + + template + const std::string lua_class::meta = std::string( "sol.stateful." ).append( classname ); + +} + +struct f { + int x; + f( ) : x( 1 ) { + } + f( int x ) : x( x ) { + } + int add( int y ) { + return x + y; + } +}; + +#include + +int main( ) { + sol::state s; + f x( 20 ); + + sol::lua_class lc{ }; + std::cout << lc.classname << std::endl; + std::cout << lc.meta << std::endl; + + s.set_function( "add", &f::add, f(10) ); + s.script( "t = add(20)" ); + std::cout << s.get( "t" ); +} diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 9328673b..f9d0b1b2 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -25,19 +25,32 @@ #include #ifdef _MSC_VER -#include +/*#include #include - +*/ namespace sol { namespace detail { std::string demangle(const std::type_info& id) { - std::string realname(2048, '\0'); - DWORD result = UnDecorateSymbolName(id.raw_name(), realname.data(), realname.size(), UNDNAME_32_BIT_DECODE); + /*std::string realname(2048, '\0'); + DWORD result = UnDecorateSymbolName(id.raw_name(), &realname[0], + static_cast(realname.size()), UNDNAME_NAME_ONLY | UNDNAME_32_BIT_DECODE); if (result == 0) return ""; realname.resize(result); + */ + const static std::string removals[ 2 ] = { + "struct ", + "class " + }; + std::string realname = id.name( ); + for ( std::size_t r = 0; r < 2; ++r ) { + auto found = realname.find( removals[ r ] ); + if ( found == std::string::npos ) + continue; + realname.erase( found, removals[r].size() ); + } return realname; } From 2243bec0523cfd8b766691f0384816c640b67215 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 25 Apr 2014 19:41:03 -0400 Subject: [PATCH 4/8] userdata now works and compiles on MSVC. It's going to take serious work to make it happen in GCC, plus the fact that 4.9 is still giving me so many errors I can't even read it... I'll let Rapptz figure it out, but later. Sexy class bindings, yes! --- main.cpp | 118 ------------------------------- sol/demangle.hpp | 56 +++++++-------- sol/lua_function.hpp | 93 +++++++------------------ sol/reference.hpp | 5 +- sol/stack.hpp | 21 ++++++ sol/state.hpp | 12 +++- sol/table.hpp | 50 ++++++++++++-- sol/traits.hpp | 6 +- sol/tuple.hpp | 4 ++ sol/types.hpp | 23 +++++++ sol/userdata.hpp | 161 +++++++++++++++++++++++++++++++++++++++++++ tests.cpp | 48 +++++++++++++ 12 files changed, 371 insertions(+), 226 deletions(-) delete mode 100644 main.cpp create mode 100644 sol/userdata.hpp diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 0532dee1..00000000 --- a/main.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include - -namespace sol { - - template - struct constructors; - - template - class lua_class { - public: - static const std::string classname; - static const std::string meta; - - private: - std::string luaname; - std::vector functionnames; - std::vector functions; - std::vector functiontable; - std::vector metatable; - - struct maker { - - static int construct( lua_State* L ) { - // First argument is now a table that represent the class to instantiate - luaL_checktype( L, 1, LUA_TTABLE ); - - lua_newtable( L ); // Create table to represent instance - - // Set first argument of new to metatable of instance - lua_pushvalue( L, 1 ); - lua_setmetatable( L, -2 ); - - // Do function lookups in metatable - lua_pushvalue( L, 1 ); - lua_setfield( L, 1, "__index" ); - - void* userdata = lua_newuserdata( L, sizeof( T ) ); - T* obj = static_cast( userdata ); - std::allocator alloc{ }; - alloc.construct( obj ); - } - - template - static int destruct( lua_State* L ) { - void* userdata = lua_touserdata( L, 0 ); - T* obj = static_cast( userdata ); - std::allocator alloc{ }; - alloc.destroy( obj ); - } - }; - - void build_function_tables( ) { - - } - - template - void build_function_tables( Ret( T::* func )( MArgs... ), std::string name, Args&&... args ) { - functionnames.push_back( std::move( name ) ); - functions.emplace_back( std::move( func ) ); - functiontable.push_back( { functionnames.back().c_str(), &lua_func::call } ); - build_function_tables( std::forward( args )... ); - } - - public: - template - lua_class( Args&&... args ) : lua_class( classname, std::forward( args )... ) { - - } - - template - lua_class( std::string name, Args&&... args ) : lua_class( name, constructors<>(), std::forward( args )... ) { - - } - - template - lua_class( std::string name, constructors c, Args&&... args ) : luaname( std::move( name ) ) { - functionnames.reserve( sizeof...( args ) ); - functiontable.reserve( sizeof...( args ) ); - metatable.reserve( sizeof...( args ) ); - build_function_tables( std::forward( args )... ); - functiontable. - } - }; - - template - const std::string lua_class::classname = detail::demangle( typeid( T ) ); - - template - const std::string lua_class::meta = std::string( "sol.stateful." ).append( classname ); - -} - -struct f { - int x; - f( ) : x( 1 ) { - } - f( int x ) : x( x ) { - } - int add( int y ) { - return x + y; - } -}; - -#include - -int main( ) { - sol::state s; - f x( 20 ); - - sol::lua_class lc{ }; - std::cout << lc.classname << std::endl; - std::cout << lc.meta << std::endl; - - s.set_function( "add", &f::add, f(10) ); - s.script( "t = add(20)" ); - std::cout << s.get( "t" ); -} diff --git a/sol/demangle.hpp b/sol/demangle.hpp index f9d0b1b2..3d1d11ba 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -32,27 +32,27 @@ namespace sol { namespace detail { - std::string demangle(const std::type_info& id) { - /*std::string realname(2048, '\0'); - DWORD result = UnDecorateSymbolName(id.raw_name(), &realname[0], - static_cast(realname.size()), UNDNAME_NAME_ONLY | UNDNAME_32_BIT_DECODE); - if (result == 0) - return ""; - realname.resize(result); - */ - const static std::string removals[ 2 ] = { - "struct ", - "class " - }; - std::string realname = id.name( ); - for ( std::size_t r = 0; r < 2; ++r ) { - auto found = realname.find( removals[ r ] ); - if ( found == std::string::npos ) - continue; - realname.erase( found, removals[r].size() ); - } - return realname; - } + std::string demangle(const std::type_info& id) { + /*std::string realname(2048, '\0'); + DWORD result = UnDecorateSymbolName(id.raw_name(), &realname[0], + static_cast(realname.size()), UNDNAME_NAME_ONLY | UNDNAME_32_BIT_DECODE); + if (result == 0) + return ""; + realname.resize(result); + */ + const static std::string removals[ 2 ] = { + "struct ", + "class " + }; + std::string realname = id.name(); + for (std::size_t r = 0; r < 2; ++r) { + auto found = realname.find(removals[ r ]); + if (found == std::string::npos) + continue; + realname.erase(found, removals[r].size()); + } + return realname; + } #elif __GNUC__ || __clang__ #include @@ -60,13 +60,13 @@ namespace detail { namespace sol { namespace detail { - 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; - } + 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 namespace sol { diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 5110e0e3..a469348a 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -26,37 +26,6 @@ #include namespace sol { -namespace detail { -template -void get_upvalue_ptr(lua_State* L, T*& data, std::size_t datasize, std::array voiddata, int& upvalue) { - for (std::size_t i = 0, d = 0; d < datasize; ++i, d += sizeof(void*)) { - voiddata[i] = lua_touserdata(L, lua_upvalueindex(upvalue++)); - } - data = reinterpret_cast(static_cast(voiddata.data())); -} -template -void get_upvalue_ptr(lua_State* L, T*& data, std::array voiddata, int& upvalue) { - get_upvalue_ptr(L, data, sizeof(T), voiddata, upvalue); -} -template -void get_upvalue_ptr(lua_State* L, T*& data, int& upvalue) { - const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*); - typedef std::array data_t; - data_t voiddata{{}}; - return get_upvalue_ptr(L, data, voiddata, upvalue); -} -template -void get_upvalue(lua_State* L, T& data, int& upvalue) { - const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*); - typedef std::array data_t; - data_t voiddata{{}}; - for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { - voiddata[i] = lua_touserdata(L, lua_upvalueindex(upvalue++)); - } - data = *reinterpret_cast(static_cast(voiddata.data())); -} -} // detail - template struct static_lua_func { @@ -83,10 +52,9 @@ struct static_lua_func { } static int call(lua_State* L) { - int upvalue = 1; - fx_t* fx; - detail::get_upvalue(L, fx, upvalue); - int r = typed_call(tuple_types(), typename fx_traits::args_type(), fx, L); + auto udata = stack::get_user(L); + fx_t* fx = udata.first; + int r = typed_call(tuple_types(), typename fx_traits::args_type(), fx, L); return r; } @@ -122,19 +90,11 @@ struct static_object_lua_func { } static int call(lua_State* L) { - const static std::size_t data_t_count = (sizeof(fx_t)+(sizeof(void*)-1)) / sizeof(void*); - typedef std::array data_t; - int upvalue = 1; - data_t data = {{}}; - fx_t* fxptr; - for (std::size_t i = 0, d = 0; d < sizeof(fx_t*); ++i, d += sizeof(void*)) { - data[i] = lua_touserdata(L, lua_upvalueindex(upvalue++)); - } - fxptr = reinterpret_cast(static_cast(data.data())); - fx_t& mem_ptr = *fxptr; - void* objectdata = lua_touserdata(L, lua_upvalueindex(upvalue++)); - T& obj = *static_cast(objectdata); - int r = typed_call(tuple_types(), typename fx_traits::args_type(), obj, mem_ptr, L); + auto memberdata = stack::get_user(L, 1); + auto objdata = stack::get_user(L, memberdata.second); + fx_t& memfx = memberdata.first; + T& obj = *objdata.first; + int r = typed_call(tuple_types(), typename fx_traits::args_type(), obj, memfx, L); return r; } @@ -145,7 +105,7 @@ struct static_object_lua_func { struct lua_func { static int call(lua_State* L) { - void** pinheritancedata = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + void** pinheritancedata = static_cast(stack::get(L, 1).value); void* inheritancedata = *pinheritancedata; if (inheritancedata == nullptr) throw sol_error("call from Lua to C++ function has null data"); @@ -156,7 +116,7 @@ struct lua_func { } static int gc(lua_State* L) { - void** puserdata = static_cast(lua_touserdata(L, 1)); + void** puserdata = static_cast(stack::get(L, 1).value); void* userdata = *puserdata; lua_func* ptr = static_cast(userdata); std::default_delete dx{}; @@ -175,15 +135,11 @@ template struct functor_lua_func : public lua_func { typedef decltype(&TFx::operator()) fx_t; typedef function_traits fx_traits; - fx_t fx; + TFx fx; template functor_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} - virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); - } - template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); @@ -202,6 +158,10 @@ struct functor_lua_func : public lua_func { stack::push(L, r); return sizeof...(Ret); } + + virtual int operator()(lua_State* L) override { + return (*this)(tuple_types(), typename fx_traits::args_type(), L); + } }; template::value> @@ -286,21 +246,21 @@ struct class_lua_func : public lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; struct functor { - T& member; + T* item; fx_t invocation; template - functor(FxArgs&&... fxargs): member(*static_cast(nullptr)), invocation(std::forward(fxargs)...) {} + functor(FxArgs&&... fxargs): item(nullptr), invocation(std::forward(fxargs)...) {} - void pre_call( lua_State* L ) { - void* userdata = lua_touserdata( L, 0 ); - T* item = static_cast( userdata ); - member = *item; - } + void pre_call(lua_State* L) { + void* userdata = lua_touserdata(L, 0); + item = static_cast(userdata); + } template typename fx_traits::return_type operator()(Args&&... args) { - return (member.*invocation)(std::forward(args)...); + T& member = *item; + return (member.*invocation)(std::forward(args)...); } } fx; @@ -309,8 +269,7 @@ struct class_lua_func : public lua_func { template int operator()(types, types t, lua_State* L) { - fx.pre_call(L); - stack::pop_call(L, fx, t); + stack::pop_call(L, fx, t); return 0; } @@ -322,13 +281,13 @@ struct class_lua_func : public lua_func { template int operator()(types, types t, lua_State* L) { typedef typename multi_return::type return_type; - fx.pre_call(L); - return_type r = stack::pop_call(L, fx, t); + return_type r = stack::pop_call(L, fx, t); stack::push(L, std::move(r)); return sizeof...(Ret); } virtual int operator()(lua_State* L) override { + fx.pre_call(L); return (*this)(tuple_types(), typename fx_traits::args_type(), L); } }; diff --git a/sol/reference.hpp b/sol/reference.hpp index 90a2d2e1..b6808960 100644 --- a/sol/reference.hpp +++ b/sol/reference.hpp @@ -46,11 +46,14 @@ public: luaL_unref(L, LUA_REGISTRYINDEX, ref); } - void push() const noexcept { lua_rawgeti(L, LUA_REGISTRYINDEX, ref); } + void pop() const noexcept { + lua_pop(L, 1); + } + reference(reference&& o) noexcept { L = o.L; ref = o.ref; diff --git a/sol/stack.hpp b/sol/stack.hpp index e89a1c92..c948dbbd 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -112,6 +112,16 @@ inline bool get(lua_State* L, int index) { return lua_toboolean(L, index) != 0; } +template<> +inline lightuserdata_t get(lua_State* L, int index) { + return {lua_touserdata(L, lua_upvalueindex(index))}; +} + +template<> +inline userdata_t get(lua_State* L, int index) { + return {lua_touserdata(L, index)}; +} + template<> inline std::string get(lua_State* L, int index) { std::string::size_type len; @@ -124,6 +134,17 @@ inline const char* get(lua_State* L, int index) { return lua_tostring(L, index); } +template +inline std::pair get_user(lua_State* L, int index = 1) { + const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{ {} }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[ i ] = stack::get(L, index++); + } + return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); +} + template inline T pop(lua_State* L) { auto r = get(L); diff --git a/sol/state.hpp b/sol/state.hpp index dea18762..80a27a79 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -144,9 +144,15 @@ public: return *this; } - template - state& set_function(T&& key, TFx&& fx, TM& mem) { - global.set_function(std::forward(key), std::forward(fx), mem); + template + state& set_function(T&& key, TFx&& fx, TObj&& obj) { + global.set_function(std::forward(key), std::forward(fx), std::forward(obj)); + return *this; + } + + template + state& set_class(userdata& user) { + global.set_class(user); return *this; } diff --git a/sol/table.hpp b/sol/table.hpp index 1688a58e..170e6817 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -25,8 +25,7 @@ #include "proxy.hpp" #include "stack.hpp" #include "lua_function.hpp" -#include -#include +#include "userdata.hpp" namespace sol { namespace detail { @@ -114,6 +113,46 @@ public: std::forward(key), std::forward(fx), std::forward(obj)); } + template + table& set_class(userdata& user) { + push(); + + lua_createtable(state(), 0, 0); + int classid = lua_gettop(state()); + + // Register metatable for user data in registry + // using the metaname key generated from the demangled name + luaL_newmetatable(state(), user.meta.c_str()); + int metaid = lua_gettop(state()); + // Meta functions: have no light up values + luaL_setfuncs(state(), user.metatable.data(), 0); + + // Regular functions: each one references an upvalue at its own index, + // resulting in [function count] upvalues + //luaL_newlib(L, functiontable.data()); + // the newlib macro doesn't have a form for when you need upvalues: + // we duplicate the work below + lua_createtable(state(), 0, user.functiontable.size() - 1); + for (std::size_t upvalues = 0; upvalues < user.functions.size(); ++upvalues) { + stack::push(state(), static_cast(user.functions[ upvalues ].get())); + } + luaL_setfuncs(state(), user.functiontable.data(), static_cast(user.functions.size())); + lua_setfield(state(), metaid, "__index"); + + // Meta functions: no upvalues + lua_createtable(state(), 0, user.metatable.size() - 1); + luaL_setfuncs(state(), user.metatable.data(), 0); // 0, for no upvalues + lua_setfield(state(), metaid, "__metatable"); + + lua_setmetatable(state(), classid); + + lua_setglobal(state(), user.luaname.c_str()); + + pop(); + + return *this; + } + size_t size() const { push(); return lua_rawlen(state(), -1); @@ -194,7 +233,7 @@ private: stack::push(state(), userobjdata); luaL_setfuncs(state(), funcreg, upvalues + 1); - lua_pop(state(), 1); + pop(); return *this; } @@ -210,11 +249,10 @@ private: }; push(); - int upvalues = stack::push_user(state(), target); luaL_setfuncs(state(), funcreg, upvalues); + pop(); - lua_pop(state(), 1); return *this; } @@ -243,7 +281,7 @@ private: push(); stack::push_user(state(), userdata, metatablename); luaL_setfuncs(state(), funcreg, 1); - lua_pop(state(), 1); + pop(); return *this; } }; diff --git a/sol/traits.hpp b/sol/traits.hpp index cb082ca7..08b6f36b 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -58,7 +58,7 @@ using Bool = std::integral_constant; namespace detail { template>::value> -struct is_function_impl : std::is_function::type> { }; +struct is_function_impl : std::is_function::type> {}; template struct is_function_impl { @@ -66,7 +66,7 @@ struct is_function_impl { using no = struct { char s[2]; }; struct F { void operator()(); }; - struct Derived : T, F { }; + struct Derived : T, F {}; template struct Check; template @@ -80,7 +80,7 @@ struct is_function_impl { } // detail template -struct Function : Bool::value> { }; +struct Function : Bool::value> {}; template struct function_traits; diff --git a/sol/tuple.hpp b/sol/tuple.hpp index cecaa3e8..8b974b3f 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -73,6 +73,10 @@ struct tuple_types : types, std::false_type {}; template struct tuple_types> : types, std::true_type {}; + +template +struct constructors {}; + } // sol #endif // SOL_TUPLE_HPP \ No newline at end of file diff --git a/sol/types.hpp b/sol/types.hpp index e84682e0..c4284d3e 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -31,6 +31,17 @@ struct nil_t {}; const nil_t nil {}; struct void_type {}; const void_type Void {}; +struct lightuserdata_t { + void* value; + lightuserdata_t(void* data) : value(data) {} + operator void* () const { return value; } +}; + +struct userdata_t { + void* value; + userdata_t(void* data) : value(data) {} + operator void* () const { return value; } +}; enum class type : int { none = LUA_TNONE, @@ -58,6 +69,8 @@ inline void type_assert(lua_State* L, int index, type expected) { } } +template +class userdata; class table; class function; class object; @@ -114,6 +127,16 @@ inline type type_of() { return type::boolean; } +template<> +inline type type_of() { + return type::lightuserdata; +} + +template<> +inline type type_of() { + return type::userdata; +} + inline bool operator==(nil_t, nil_t) { return true; } inline bool operator!=(nil_t, nil_t) { return false; } } // sol diff --git a/sol/userdata.hpp b/sol/userdata.hpp new file mode 100644 index 00000000..817dc521 --- /dev/null +++ b/sol/userdata.hpp @@ -0,0 +1,161 @@ +// The MIT License (MIT) + +// Copyright (c) 2013 Danny Y., Rapptz + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_USERDATA_HPP +#define SOL_USERDATA_HPP + +#include +#include +#include +#include + +namespace sol { + +template +class userdata { +private: + friend table; + static const std::string classname; + static const std::string meta; + + std::string luaname; + std::vector functionnames; + std::vector> functions; + std::vector functiontable; + std::vector metatable; + + struct constructor { + static int construct(lua_State* L) { + // First argument is now a table that represent the class to instantiate + luaL_checktype(L, 1, LUA_TTABLE); + + lua_createtable(L, 0, 0); // Create table to represent instance + + // Set first argument of new to metatable of instance + lua_pushvalue(L, 1); + lua_setmetatable(L, -2); + + // Do function lookups in metatable + lua_pushvalue(L, 1); + lua_setfield(L, 1, "__index"); + + void* userdata = lua_newuserdata(L, sizeof(T)); + T* obj = static_cast(userdata); + std::allocator alloc{}; + alloc.construct(obj); + + luaL_getmetatable(L, meta.c_str()); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "__self"); + + return 1; + } + }; + + template + struct destructor { + static int destruct(lua_State* L) { + for (std::size_t i = 0; i < n; ++i) { + lightuserdata_t luserdata = stack::get(L, i); + } + userdata_t userdata = stack::get(L, 0); + T* obj = static_cast(userdata.value); + std::allocator alloc{}; + alloc.destroy(obj); + + return 0; + } + }; + + template + struct class_func { + static int call(lua_State* L) { + // Zero-based template parameter, but upvalues start at 1 + void* inheritancedata = stack::get(L, i + 1); + if (inheritancedata == nullptr) + throw sol_error("call from Lua to C++ function has null data"); + lua_func* pfx = static_cast(inheritancedata); + lua_func& fx = *pfx; + int r = fx(L); + return r; + } + }; + + template + void build_function_tables() { + + } + + template + void build_function_tables(Ret(T::* func)(MArgs...), std::string name, Args&&... args) { + typedef typename std::decay::type fx_t; + functionnames.push_back(std::move(name)); + functions.emplace_back(std::make_unique>(std::move(func))); + functiontable.push_back({ functionnames.back().c_str(), &class_func::call }); + build_function_tables(std::forward(args)...); + } + +public: + template + userdata(Args&&... args) : userdata(classname, std::forward(args)...) { + + } + + template + userdata(std::string name, Args&&... args) : userdata(name, constructors<>(), std::forward(args)...) { + + } + + template + userdata(constructors c, Args&&... args) : userdata(classname, std::move(c), std::forward(args)...) { + + } + + template + userdata(std::string name, constructors c, Args&&... args) : luaname(std::move(name)) { + functionnames.reserve(sizeof...(args)); + functiontable.reserve(sizeof...(args)); + functions.reserve(sizeof...(args)); + metatable.reserve(sizeof...(args)); + build_function_tables<0>(std::forward(args)...); + + functionnames.push_back("new"); + functiontable.push_back({ functionnames.back().c_str(), &constructor::construct }); + functiontable.push_back({ nullptr, nullptr }); + + metatable.push_back({ "__gc", &destructor::destruct }); + metatable.push_back({ nullptr, nullptr }); + } + + void register_into(const table& s) { + + } +}; + +template +const std::string userdata::classname = detail::demangle(typeid(T)); + +template +const std::string userdata::meta = std::string("sol.stateful.").append(classname); + +} + +#endif SOL_USERDATA_HPP diff --git a/tests.cpp b/tests.cpp index c4e546a7..c916a79d 100644 --- a/tests.cpp +++ b/tests.cpp @@ -16,6 +16,26 @@ struct object { }; +struct fuser { + int x; + + fuser( ) : x( 0 ) { + + } + + fuser( int x ) : x( x ) { + + } + + int add( int y ) { + return x + y; + } + + int add2( int y ) { + return x + y + 2; + } +}; + int plop_xyz(int x, int y, std::string z) { std::cout << x << " " << y << " " << z << std::endl; return 11; @@ -324,3 +344,31 @@ TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works REQUIRE_NOTHROW(assert1(lua.global_table())); } + +TEST_CASE( "tables/userdata", "Show that we can create classes from userdata and use them" ) { + + sol::state lua; + + sol::userdata lc{ &fuser::add, "add", &fuser::add2, "add2" }; + lua.set_class( lc ); + + lua.script( "a = fuser:new()\n" + "b = a:add(1)\n" + "c = a:add2(1)\n" + "\n" ); + + sol::object a = lua.get( "a" ); + sol::object b = lua.get( "b" ); + sol::object c = lua.get( "c" ); + REQUIRE( ( a.is( ) ) ); + auto atype = a.get_type( ); + auto btype = b.get_type( ); + auto ctype = c.get_type( ); + REQUIRE( ( atype == sol::type::table ) ); + REQUIRE( ( btype == sol::type::number ) ); + REQUIRE( ( ctype == sol::type::number ) ); + int bresult = b.as( ); + int cresult = c.as( ); + REQUIRE( bresult == 1 ); + REQUIRE( cresult == 3 ); +} \ No newline at end of file From 23ed27df89fcf3eafe8adcfb7e093a21abca42ee Mon Sep 17 00:00:00 2001 From: Rapptz Date: Fri, 25 Apr 2014 20:11:00 -0400 Subject: [PATCH 5/8] Renamed DEPRECATE to SOL_DEPRECATED --- sol/deprecate.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sol/deprecate.hpp b/sol/deprecate.hpp index bd14b5c1..59b23729 100644 --- a/sol/deprecate.hpp +++ b/sol/deprecate.hpp @@ -22,14 +22,14 @@ #ifndef SOL_DEPRECATE_HPP #define SOL_DEPRECATE_HPP -#ifndef DEPRECATE -#ifdef _MSC_VER -#define DEPRECATE __declspec(deprecated) -#elif __GNUC__ -#define DEPRECATE __attribute__((deprecated)) -#else -#define DEPRECATE [[deprecated]] -#endif // VC++ || GCC || Others -#endif // DEPRECATE +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED #endif // SOL_DEPRECATE_HPP \ No newline at end of file From 44eab5a1642cf18f79bfab1e860fc8976f49850e Mon Sep 17 00:00:00 2001 From: Rapptz Date: Fri, 25 Apr 2014 20:19:31 -0400 Subject: [PATCH 6/8] Refactor demangle.hpp to look a bit nicer --- sol/demangle.hpp | 69 ++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 3d1d11ba..d2ef43b7 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -24,57 +24,40 @@ #include -#ifdef _MSC_VER -/*#include -#include -*/ -namespace sol { -namespace detail { - - - std::string demangle(const std::type_info& id) { - /*std::string realname(2048, '\0'); - DWORD result = UnDecorateSymbolName(id.raw_name(), &realname[0], - static_cast(realname.size()), UNDNAME_NAME_ONLY | UNDNAME_32_BIT_DECODE); - if (result == 0) - return ""; - realname.resize(result); - */ - const static std::string removals[ 2 ] = { - "struct ", - "class " - }; - std::string realname = id.name(); - for (std::size_t r = 0; r < 2; ++r) { - auto found = realname.find(removals[ r ]); - if (found == std::string::npos) - continue; - realname.erase(found, removals[r].size()); - } - return realname; - } - -#elif __GNUC__ || __clang__ +#if defined(__GNUC__) || defined(__clang__) #include +#endif namespace sol { namespace detail { +#ifdef _MSC_VER +std::string demangle(const std::type_info& id) { + const static std::string removals[2] = { "struct ", "class " }; + std::string realname = id.name(); + for(std::size_t r = 0; r < 2; ++r) { + auto found = realname.find(removals[r]); - 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; + if(found == std::string::npos) { + continue; + } + + realname.erase(found, removals[r].size()); } + 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 -namespace sol { -namespace detail { - -#error Implement demangling for this platform -#endif // VC++ || GCC || Others - +#error Compiler not supported for demangling +#endif // compilers } // detail } // sol From 6b54f99e50a31f1e218f0a64a8b0008f645a7d4c Mon Sep 17 00:00:00 2001 From: Rapptz Date: Fri, 25 Apr 2014 20:42:38 -0400 Subject: [PATCH 7/8] Do some renaming of lua_function.hpp and fix some compiler errors --- sol/lua_function.hpp | 89 ++++++++++++++++++++++---------------------- sol/userdata.hpp | 4 +- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index a469348a..06e3979a 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -27,24 +27,24 @@ namespace sol { -template +template struct static_lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; + typedef typename std::remove_pointer::type>::type function_type; + typedef function_traits traits_type; template - static int typed_call(types, types t, fx_t* fx, lua_State* L) { + static int typed_call(types, types t, function_type* fx, lua_State* L) { stack::pop_call(L, fx, t); return 0; } template - static int typed_call(types<>, types t, fx_t* fx, lua_State* L) { + static int typed_call(types<>, types t, function_type* fx, lua_State* L) { return typed_call(types(), t, fx, L); } template - static int typed_call(types, types t, fx_t* fx, lua_State* L) { + static int typed_call(types, types t, function_type* fx, lua_State* L) { typedef typename multi_return::type return_type; return_type r = stack::pop_call(L, fx, t); stack::push(L, std::move(r)); @@ -52,9 +52,9 @@ struct static_lua_func { } static int call(lua_State* L) { - auto udata = stack::get_user(L); - fx_t* fx = udata.first; - int r = typed_call(tuple_types(), typename fx_traits::args_type(), fx, L); + auto udata = stack::get_user(L); + function_type* fx = udata.first; + int r = typed_call(tuple_types(), typename traits_type::args_type(), fx, L); return r; } @@ -63,25 +63,25 @@ struct static_lua_func { } }; -template +template struct static_object_lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; + typedef typename std::remove_pointer::type>::type function_type; + typedef function_traits traits_type; template - static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { + 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; } template - static int typed_call(types<>, types t, T& item, fx_t& ifx, lua_State* L) { + static int typed_call(types<>, types t, T& item, function_type& ifx, lua_State* L) { return typed_call(types(), t, item, ifx, L); } template - static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { + static int typed_call(types, types, T& item, function_type& ifx, lua_State* L) { typedef typename multi_return::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()); @@ -90,11 +90,11 @@ struct static_object_lua_func { } static int call(lua_State* L) { - auto memberdata = stack::get_user(L, 1); - auto objdata = stack::get_user(L, memberdata.second); - fx_t& memfx = memberdata.first; - T& obj = *objdata.first; - int r = typed_call(tuple_types(), typename fx_traits::args_type(), obj, memfx, L); + auto memberdata = stack::get_user(L, 1); + auto objdata = stack::get_user(L, memberdata.second); + function_type& memfx = memberdata.first; + T& obj = *objdata.first; + int r = typed_call(tuple_types(), typename traits_type::args_type(), obj, memfx, L); return r; } @@ -107,8 +107,9 @@ struct lua_func { static int call(lua_State* L) { void** pinheritancedata = static_cast(stack::get(L, 1).value); void* inheritancedata = *pinheritancedata; - if (inheritancedata == nullptr) + if (inheritancedata == nullptr) { throw sol_error("call from Lua to C++ function has null data"); + } lua_func* pfx = static_cast(inheritancedata); lua_func& fx = *pfx; int r = fx(L); @@ -131,11 +132,11 @@ struct lua_func { virtual ~lua_func() {} }; -template +template struct functor_lua_func : public lua_func { - typedef decltype(&TFx::operator()) fx_t; - typedef function_traits fx_traits; - TFx fx; + typedef decltype(&Function::operator()) function_type; + typedef function_traits traits_type; + Function fx; template functor_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} @@ -160,15 +161,15 @@ struct functor_lua_func : public lua_func { } virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); + return (*this)(tuple_types(), typename traits_type::args_type(), L); } }; -template::value> +template::value> struct function_lua_func : public lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; - fx_t fx; + typedef typename std::remove_pointer::type>::type function_type; + typedef function_traits traits_type; + function_type fx; template function_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} @@ -193,23 +194,23 @@ struct function_lua_func : public lua_func { } virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); + return (*this)(tuple_types(), typename traits_type::args_type(), L); } }; -template -struct function_lua_func : public lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; +template +struct function_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type function_type; + typedef function_traits traits_type; struct functor { T member; - fx_t invocation; + function_type invocation; template functor(T m, FxArgs&&... fxargs): member(std::move(m)), invocation(std::forward(fxargs)...) {} template - typename fx_traits::return_type operator()(Args&&... args) { + typename traits_type::return_type operator()(Args&&... args) { return (member.*invocation)(std::forward(args)...); } } fx; @@ -237,17 +238,17 @@ struct function_lua_func : public lua_func { } virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); + return (*this)(tuple_types(), typename traits_type::args_type(), L); } }; -template +template struct class_lua_func : public lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; + typedef typename std::remove_pointer::type>::type function_type; + typedef function_traits traits_type; struct functor { T* item; - fx_t invocation; + function_type invocation; template functor(FxArgs&&... fxargs): item(nullptr), invocation(std::forward(fxargs)...) {} @@ -258,7 +259,7 @@ struct class_lua_func : public lua_func { } template - typename fx_traits::return_type operator()(Args&&... args) { + typename traits_type::return_type operator()(Args&&... args) { T& member = *item; return (member.*invocation)(std::forward(args)...); } @@ -288,7 +289,7 @@ struct class_lua_func : public lua_func { virtual int operator()(lua_State* L) override { fx.pre_call(L); - return (*this)(tuple_types(), typename fx_traits::args_type(), L); + return (*this)(tuple_types(), typename traits_type::args_type(), L); } }; diff --git a/sol/userdata.hpp b/sol/userdata.hpp index 817dc521..4c53d2a8 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -130,7 +130,7 @@ public: } template - userdata(std::string name, constructors c, Args&&... args) : luaname(std::move(name)) { + userdata(std::string name, constructors, Args&&... args) : luaname(std::move(name)) { functionnames.reserve(sizeof...(args)); functiontable.reserve(sizeof...(args)); functions.reserve(sizeof...(args)); @@ -158,4 +158,4 @@ const std::string userdata::meta = std::string("sol.stateful.").append(classn } -#endif SOL_USERDATA_HPP +#endif // SOL_USERDATA_HPP From c9bf032d36800bdfb136fa57d6c67b3b67d3c7e0 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Fri, 25 Apr 2014 20:53:36 -0400 Subject: [PATCH 8/8] Fix all compile errors on GCC --- sol/userdata.hpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/sol/userdata.hpp b/sol/userdata.hpp index 4c53d2a8..8f211610 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -22,12 +22,18 @@ #ifndef SOL_USERDATA_HPP #define SOL_USERDATA_HPP -#include -#include -#include +#include "state.hpp" +#include "lua_function.hpp" +#include "demangle.hpp" #include namespace sol { +namespace detail { +template +inline std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} +} // detail template class userdata { @@ -70,12 +76,15 @@ private: } }; - template + template struct destructor { static int destruct(lua_State* L) { - for (std::size_t i = 0; i < n; ++i) { + for(std::size_t i = 0; i < n; ++i) { lightuserdata_t luserdata = stack::get(L, i); + // make warnings shut up + (void)luserdata; } + userdata_t userdata = stack::get(L, 0); T* obj = static_cast(userdata.value); std::allocator alloc{}; @@ -108,26 +117,20 @@ private: void build_function_tables(Ret(T::* func)(MArgs...), std::string name, Args&&... args) { typedef typename std::decay::type fx_t; functionnames.push_back(std::move(name)); - functions.emplace_back(std::make_unique>(std::move(func))); + functions.emplace_back(detail::make_unique>(std::move(func))); functiontable.push_back({ functionnames.back().c_str(), &class_func::call }); build_function_tables(std::forward(args)...); } public: template - userdata(Args&&... args) : userdata(classname, std::forward(args)...) { - - } + userdata(Args&&... args) : userdata(classname, std::forward(args)...) {} template - userdata(std::string name, Args&&... args) : userdata(name, constructors<>(), std::forward(args)...) { - - } + userdata(std::string name, Args&&... args) : userdata(name, constructors<>(), std::forward(args)...) {} template - userdata(constructors c, Args&&... args) : userdata(classname, std::move(c), std::forward(args)...) { - - } + userdata(constructors c, Args&&... args) : userdata(classname, std::move(c), std::forward(args)...) {} template userdata(std::string name, constructors, Args&&... args) : luaname(std::move(name)) { @@ -145,9 +148,7 @@ public: metatable.push_back({ nullptr, nullptr }); } - void register_into(const table& s) { - - } + void register_into(const table& s) { } }; template