From 24c76d3e03463c79a7bab359a6b14251eaf35262 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 1 Dec 2013 17:27:17 -0500 Subject: [PATCH 01/11] Added VS2013 files to gitignore. --- .gitignore | 24 +++- sol/state.hpp | 370 +++++++++++++++++++++++++------------------------- 2 files changed, 202 insertions(+), 192 deletions(-) diff --git a/.gitignore b/.gitignore index 39dc9054..a290d689 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,17 @@ -obj/* -bin/* -*.ninja* -demacro.txt -Shinobi2 -dev.* -main.cpp +obj/* +bin/* +*.ninja* +demacro.txt +Shinobi2 +dev.* +main.cpp +lua-5.2.2/ +Debug/ +Release/ +x64/ +*.vcxproj +*.vcxproj.filters +*.tlog +*.lastbuildstate +*.idb +*.sln diff --git a/sol/state.hpp b/sol/state.hpp index 985b5c19..3489d0cd 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -1,186 +1,186 @@ -// 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_STATE_HPP -#define SOL_STATE_HPP - -#include "error.hpp" -#include "table.hpp" -#include - -namespace sol { -namespace detail { -template -struct are_same : std::true_type {}; - -template -struct are_same : std::integral_constant{} && are_same{}> {}; - -int atpanic(lua_State* L) { - throw sol_error(lua_tostring(L, -1)); -} -} // detail - -enum class lib : char { - base, - package, - coroutine, - string, - os, - math, - table, - debug, - bit32, - io, - count -}; - -class state { -private: - std::unique_ptr L; - table reg; - table global; -public: - state(): - L(luaL_newstate(), lua_close), - reg(L.get(), LUA_REGISTRYINDEX), - global(reg.get(LUA_RIDX_GLOBALS)) { - lua_atpanic(L.get(), detail::atpanic); - } - - state(const std::string& filename): - L(luaL_newstate(), lua_close), - reg(L.get(), LUA_REGISTRYINDEX), - global(reg.get
(LUA_RIDX_GLOBALS)) { - lua_atpanic(L.get(), detail::atpanic); - open_file(filename); - } - - template - void open_libraries(Args&&... args) { - static_assert(detail::are_same{}, "all types must be libraries"); - if(sizeof...(args) == 0) { - luaL_openlibs(L.get()); - return; - } - - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - - for(auto&& library : libraries) { - switch(library) { - case lib::base: - luaL_requiref(L.get(), "base", luaopen_base, 1); - break; - case lib::package: - luaL_requiref(L.get(), "package", luaopen_package, 1); - break; - case lib::coroutine: - luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); - break; - case lib::string: - luaL_requiref(L.get(), "string", luaopen_string, 1); - break; - case lib::table: - luaL_requiref(L.get(), "table", luaopen_table, 1); - break; - case lib::math: - luaL_requiref(L.get(), "math", luaopen_math, 1); - break; - case lib::bit32: - luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); - break; - case lib::io: - luaL_requiref(L.get(), "io", luaopen_io, 1); - break; - case lib::os: - luaL_requiref(L.get(), "os", luaopen_os, 1); - break; - case lib::debug: - luaL_requiref(L.get(), "debug", luaopen_debug, 1); - break; - case lib::count: - break; - } - } - } - - void script(const std::string& code) { - if(luaL_dostring(L.get(), code.c_str())) { - lua_error(L.get()); - } - } - - void open_file(const std::string& filename) { - if(luaL_dofile(L.get(), filename.c_str())) { - lua_error(L.get()); - } - } - - template - T get(U&& key) const { - return global.get(std::forward(key)); - } - - template - state& set(T&& key, U&& value) { - global.set(std::forward(key), std::forward(value)); - return *this; - } - - template - table create_table(T&& key, int narr = 0, int nrec = 0) { - if(narr == 0 && nrec == 0) { - lua_newtable(L.get()); - } - else { - lua_createtable(L.get(), narr, nrec); - } - - table result(L.get()); - lua_pop(L.get(), 1); - global.set(std::forward(key), result); - return result; - } - - table create_table(int narr = 0, int nrec = 0) { - if(narr == 0 && nrec == 0) { - lua_newtable(L.get()); - } - else { - lua_createtable(L.get(), narr, nrec); - } - - table result(L.get()); - lua_pop(L.get(), 1); - return result; - } - - table global_table() const { - return global; - } - - table registry() const { - return reg; - } -}; -} // sol - +// 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_STATE_HPP +#define SOL_STATE_HPP + +#include "error.hpp" +#include "table.hpp" +#include + +namespace sol { +namespace detail { +template +struct are_same : std::true_type {}; + +template +struct are_same : std::integral_constant::value && are_same::value> {}; + +int atpanic(lua_State* L) { + throw sol_error(lua_tostring(L, -1)); +} +} // detail + +enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + count +}; + +class state { +private: + std::unique_ptr L; + table reg; + table global; +public: + state(): + L(luaL_newstate(), lua_close), + reg(L.get(), LUA_REGISTRYINDEX), + global(reg.get
(LUA_RIDX_GLOBALS)) { + lua_atpanic(L.get(), detail::atpanic); + } + + state(const std::string& filename): + L(luaL_newstate(), lua_close), + reg(L.get(), LUA_REGISTRYINDEX), + global(reg.get
(LUA_RIDX_GLOBALS)) { + lua_atpanic(L.get(), detail::atpanic); + open_file(filename); + } + + template + void open_libraries(Args&&... args) { + static_assert(detail::are_same{}, "all types must be libraries"); + if(sizeof...(args) == 0) { + luaL_openlibs(L.get()); + return; + } + + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; + + for(auto&& library : libraries) { + switch(library) { + case lib::base: + luaL_requiref(L.get(), "base", luaopen_base, 1); + break; + case lib::package: + luaL_requiref(L.get(), "package", luaopen_package, 1); + break; + case lib::coroutine: + luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); + break; + case lib::string: + luaL_requiref(L.get(), "string", luaopen_string, 1); + break; + case lib::table: + luaL_requiref(L.get(), "table", luaopen_table, 1); + break; + case lib::math: + luaL_requiref(L.get(), "math", luaopen_math, 1); + break; + case lib::bit32: + luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); + break; + case lib::io: + luaL_requiref(L.get(), "io", luaopen_io, 1); + break; + case lib::os: + luaL_requiref(L.get(), "os", luaopen_os, 1); + break; + case lib::debug: + luaL_requiref(L.get(), "debug", luaopen_debug, 1); + break; + case lib::count: + break; + } + } + } + + void script(const std::string& code) { + if(luaL_dostring(L.get(), code.c_str())) { + lua_error(L.get()); + } + } + + void open_file(const std::string& filename) { + if(luaL_dofile(L.get(), filename.c_str())) { + lua_error(L.get()); + } + } + + template + T get(U&& key) const { + return global.get(std::forward(key)); + } + + template + state& set(T&& key, U&& value) { + global.set(std::forward(key), std::forward(value)); + return *this; + } + + template + table create_table(T&& key, int narr = 0, int nrec = 0) { + if(narr == 0 && nrec == 0) { + lua_newtable(L.get()); + } + else { + lua_createtable(L.get(), narr, nrec); + } + + table result(L.get()); + lua_pop(L.get(), 1); + global.set(std::forward(key), result); + return result; + } + + table create_table(int narr = 0, int nrec = 0) { + if(narr == 0 && nrec == 0) { + lua_newtable(L.get()); + } + else { + lua_createtable(L.get(), narr, nrec); + } + + table result(L.get()); + lua_pop(L.get(), 1); + return result; + } + + table global_table() const { + return global; + } + + table registry() const { + return reg; + } +}; +} // sol + #endif // SOL_STATE_HPP \ No newline at end of file From 9f79e8c57346251f73389d31a67a48c2701dd8c3 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 1 Dec 2013 18:15:26 -0500 Subject: [PATCH 02/11] function header with addition to sol.hpp so that a person can do function invocations on lua functions without explicitly adding sol/functions.hpp --- sol.hpp | 55 ++++++++++++++++++++++++------------------------ sol/function.hpp | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 sol/function.hpp diff --git a/sol.hpp b/sol.hpp index fb2fdf67..fbf44a8f 100644 --- a/sol.hpp +++ b/sol.hpp @@ -1,28 +1,29 @@ -// 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_HPP -#define SOL_HPP - -#include "sol/state.hpp" -#include "sol/object.hpp" - +// 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_HPP +#define SOL_HPP + +#include "sol/state.hpp" +#include "sol/object.hpp" +#include "sol/function.hpp" + #endif // SOL_HPP \ No newline at end of file diff --git a/sol/function.hpp b/sol/function.hpp new file mode 100644 index 00000000..e0a4f1bf --- /dev/null +++ b/sol/function.hpp @@ -0,0 +1,41 @@ +#ifndef SOL_FUNCTION_HPP +#define SOL_FUNCTION_HPP + +#include +#include +#include + +namespace sol { +class function : virtual public reference { +private: + template + void push_args( Args&&... args ) { + auto L = state( ); + using swallow = char []; + void( swallow{ ( stack::push( L, std::forward( args ) ), '\0' )... } ); + } +public: + function( ) : reference( ) {} + function( lua_State* L, int index = -1 ) : reference( L, index ) { + type_assert( L, index, type::function ); + } + + template + T invoke( Args&&... args ) { + push( ); + push_args( std::forward( args )... ); + lua_pcall( state( ), sizeof...( Args ), 1, 0 ); + return stack::pop( state( ) ); + } + + template + void invoke( Args&&... args ) { + push( ); + push_args( std::forward( args )... ); + lua_pcall( state( ), sizeof...( Args ), 0, 0 ); + } +}; +} // sol + + +#endif // SOL_FUNCTION_HPP \ No newline at end of file From ebf4908c27d5561852b41f9da258e60854cc116d Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 1 Dec 2013 18:57:28 -0500 Subject: [PATCH 03/11] Formatting corrections --- sol/function.hpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index e0a4f1bf..5aee99b0 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -1,38 +1,38 @@ #ifndef SOL_FUNCTION_HPP #define SOL_FUNCTION_HPP -#include -#include -#include +#include "reference.hpp" +#include "tuple.hpp" +#include "stack.hpp" namespace sol { class function : virtual public reference { private: template - void push_args( Args&&... args ) { - auto L = state( ); + void push_args(Args&&... args) { + auto L = state(); using swallow = char []; - void( swallow{ ( stack::push( L, std::forward( args ) ), '\0' )... } ); + void( swallow{ (stack::push(L, std::forward(args)), '\0')... } ); } public: - function( ) : reference( ) {} - function( lua_State* L, int index = -1 ) : reference( L, index ) { - type_assert( L, index, type::function ); + function() : reference() {} + function(lua_State* L, int index = -1) : reference(L, index) { + type_assert(L, index, type::function); } template - T invoke( Args&&... args ) { - push( ); - push_args( std::forward( args )... ); - lua_pcall( state( ), sizeof...( Args ), 1, 0 ); - return stack::pop( state( ) ); + T invoke(Args&&... args) { + push(); + push_args(std::forward(args)...); + lua_pcall(state(), sizeof...(Args), 1, 0); + return stack::pop(state()); } template - void invoke( Args&&... args ) { - push( ); - push_args( std::forward( args )... ); - lua_pcall( state( ), sizeof...( Args ), 0, 0 ); + void invoke(Args&&... args) { + push(); + push_args(std::forward(args)...); + lua_pcall(state(), sizeof...(Args), 0, 0); } }; } // sol From cea7e9be6419c563c63ad33953603a0f94b7a376 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 1 Dec 2013 19:00:01 -0500 Subject: [PATCH 04/11] Updated gitignore for test files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a290d689..9ca6142f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ demacro.txt Shinobi2 dev.* main.cpp +sol.scratch.cpp lua-5.2.2/ Debug/ Release/ @@ -15,3 +16,4 @@ x64/ *.lastbuildstate *.idb *.sln +*.gitattributes From f67b21b5257291edf3043ac26c29b57bffe528aa Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 14:22:51 -0500 Subject: [PATCH 05/11] The solution technically works, but there's some stack corruption going on somewhere that I can quite track down, even when calling a void function with no parameters. I'll have to look into it... --- sol/function.hpp | 125 +++++++++----- sol/functional.hpp | 102 ++++++++++++ sol/lua_function.hpp | 138 ++++++++++++++++ sol/stack.hpp | 33 ++++ sol/state.hpp | 378 ++++++++++++++++++++++--------------------- sol/table.hpp | 50 ++++++ sol/tuple.hpp | 25 ++- sol/types.hpp | 4 +- 8 files changed, 614 insertions(+), 241 deletions(-) create mode 100644 sol/functional.hpp create mode 100644 sol/lua_function.hpp diff --git a/sol/function.hpp b/sol/function.hpp index 5aee99b0..059c204b 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -1,41 +1,84 @@ -#ifndef SOL_FUNCTION_HPP -#define SOL_FUNCTION_HPP - -#include "reference.hpp" -#include "tuple.hpp" -#include "stack.hpp" - -namespace sol { -class function : virtual public reference { -private: - template - void push_args(Args&&... args) { - auto L = state(); - using swallow = char []; - void( swallow{ (stack::push(L, std::forward(args)), '\0')... } ); - } -public: - function() : reference() {} - function(lua_State* L, int index = -1) : reference(L, index) { - type_assert(L, index, type::function); - } - - template - T invoke(Args&&... args) { - push(); - push_args(std::forward(args)...); - lua_pcall(state(), sizeof...(Args), 1, 0); - return stack::pop(state()); - } - - template - void invoke(Args&&... args) { - push(); - push_args(std::forward(args)...); - lua_pcall(state(), sizeof...(Args), 0, 0); - } -}; -} // sol - - -#endif // SOL_FUNCTION_HPP \ No newline at end of file +// 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_FUNCTION_HPP +#define SOL_FUNCTION_HPP + +#include "reference.hpp" +#include "tuple.hpp" +#include "stack.hpp" + +namespace sol { +class function : virtual public reference { +private: + template + void push_args(Args&&... args) const { + auto L = state(); + using swallow = char[ ]; + void(swallow{ (stack::push(L, std::forward(args)), '\0')... }); + } + + template + struct invoker { + template + static std::tuple call( const function& ref, Args&&... args ) { + ref.push( ); + ref.push_args( std::forward( args )... ); + lua_pcall( ref.state( ), sizeof...( Args ), sizeof...( Ret ), 0 ); + return std::make_tuple( stack::pop( ref.state( ) )... ); + } + }; + + template<> + struct invoker<> { + template + static void call( const function& ref, Args&&... args ) { + ref.push( ); + ref.push_args( std::forward( args )... ); + lua_pcall( ref.state( ), sizeof...( Args ), 0, 0 ); + } + }; + + template + struct invoker { + template + static T call( const function& ref, Args&&... args ) { + ref.push( ); + ref.push_args( std::forward( args )... ); + lua_pcall( ref.state( ), sizeof...( Args ), 1, 0 ); + return stack::pop( ref.state( ) ); + } + }; + +public: + function() : reference() {} + function(lua_State* L, int index = -1) : reference(L, index) { + type_assert(L, index, type::function); + } + + template + auto invoke( Args&&... args ) { + return invoker::call( *this, std::forward( args )... ); + } +}; +} // sol + +#endif // SOL_FUNCTION_HPP diff --git a/sol/functional.hpp b/sol/functional.hpp new file mode 100644 index 00000000..349d8d05 --- /dev/null +++ b/sol/functional.hpp @@ -0,0 +1,102 @@ +// 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. + +#include "tuple.hpp" + +#ifndef SOL_FUNCTIONAL_HPP +#define SOL_FUNCTIONAL_HPP + +namespace sol { +namespace detail { + +template +struct function_traits; + +template +struct function_traits { + static const std::size_t arity = sizeof...( Tn ); + static const bool is_member_function = true; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R( T::* func_t )( Tn... ); + typedef R( T::* func_pointer_t )( Tn... ); + typedef R return_t; + template + using arg_n = std::tuple_element; +}; + +template +struct function_traits { + static const std::size_t arity = sizeof...( Tn ); + static const bool is_member_function = true; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R( T::* func_t )( Tn... ); + typedef R( T::* func_pointer_t )( Tn... ); + typedef R return_t; + template + using arg_n = std::tuple_element; +}; + +template +struct function_traits { + static const std::size_t arity = sizeof...( Tn ); + static const bool is_member_function = false; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R( func_t )( Tn... ); + typedef R( *func_pointer_t )( Tn... ); + typedef R return_t; + template + using arg_n = std::tuple_element; +}; + +template +struct function_traits { + static const std::size_t arity = sizeof...( Tn ); + static const bool is_member_function = false; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R( func_t )( Tn... ); + typedef R( *func_pointer_t )( Tn... ); + typedef R return_t; + template + using arg_n = std::tuple_element; +}; + +using std::get; + +template +inline auto call( Function f, const Tuple& t, indices ) -> decltype( f( get( t )... ) ) { + return f( get( t )... ); +} + +} // detail + +template +inline auto call( Function f, const std::tuple& t ) -> decltype( detail::call( f, t, detail::build_indices{} ) ) { + return call( f, t, detail::build_indices{} ); +} + +} // sol + + +#endif // SOL_FUNCTIONAL_HPP \ No newline at end of file diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp new file mode 100644 index 00000000..1d09b0ee --- /dev/null +++ b/sol/lua_function.hpp @@ -0,0 +1,138 @@ +// 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_LUA_FUNC_HPP +#define SOL_LUA_FUNC_HPP + +#include "functional.hpp" +#include "stack.hpp" + +namespace sol { +namespace detail { + + struct lua_func { + virtual int operator () ( lua_State* L ) { + throw sol_error( "Failure to call specialized wrapped C++ function from lua" ); + } + + virtual ~lua_func( ) {}; + }; + + template + struct lambda_lua_func : public lua_func { + typedef decltype( &TFx::operator() ) fx_t; + typedef function_traits fx_traits; + TFx fx; + + template + lambda_lua_func( TFxn&&... fxn ) : fx( std::forward( fxn )... ) { + + } + + virtual int operator () ( lua_State* L ) override { + return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); + } + + template + int operator()( types, types t, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + return 0; + } + + template + int operator()( types, types t, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + stack::push( L, r ); + return sizeof...( TRn ); + } + }; + + template ::value> + struct explicit_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type fx_t; + typedef function_traits fx_traits; + TFx fx; + + template + explicit_lua_func( TFxn&&... fxn ) : fx( std::forward( fxn )... ) { + + } + + virtual int operator () ( lua_State* L ) override { + return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); + } + + template + int operator () ( types, types t, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + return 0; + } + + template + int operator () ( types, types t, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + stack::push( L, r ); + return sizeof...( TRn ); + } + }; + + template + struct explicit_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type fx_t; + typedef function_traits fx_traits; + T* member; + TFx fx; + + template + explicit_lua_func( T* m, TFxn&&... fxn ) : member(m), fx( std::forward( fxn )... ) { + + } + + virtual int operator () ( lua_State* L ) override { + return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); + } + + template + int operator () ( types, types, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + return 0; + } + + template + int operator () ( types, types t, lua_State* L ) { + auto r = stack::pop_call( L, fx, t ); + stack::push( L, r ); + return sizeof...( TRn ); + } + }; + + + int lua_cfun( lua_State* L ) { + void* bridgedata = lua_touserdata( L, lua_upvalueindex( 1 ) ); + auto* fx = static_cast( bridgedata ); + int r = fx->operator()( L ); + return r; + } + +} // detail +} // sol + +#endif // SOL_LUA_FUNC_HPP diff --git a/sol/stack.hpp b/sol/stack.hpp index adba07ec..e2863822 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -23,6 +23,7 @@ #define SOL_STACK_HPP #include "reference.hpp" +#include "tuple.hpp" #include #include @@ -35,6 +36,19 @@ using DisableIf = typename std::enable_if::type; namespace stack { namespace detail { +template +auto ltr_pop( T&& extra, F f, types<>, Vs&&... vs ) + -> decltype( f( std::forward( vs )... ) ) { + return f( std::forward( vs )... ); +} + +// take head, produce value from it, pass after other values +template +auto ltr_pop( lua_State* L, F f, types, Vs&&... vs ) +-> decltype( ltr_pop( L, f, types{}, std::forward( vs )..., stack::pop( L ) ) ) { + return ltr_pop( L, f, types{}, std::forward( vs )..., stack::pop( L ) ); +} + template inline T get_unsigned(lua_State* L, std::true_type, int index = -1) { return lua_tounsigned(L, index); @@ -150,6 +164,25 @@ inline void push(lua_State* L, const char (&str)[N]) { inline void push(lua_State* L, const std::string& str) { lua_pushlstring(L, str.c_str(), str.size()); } + +namespace detail { +template +inline void push( lua_State* L, indices, const T& tuplen ) { + using swallow = char []; + void( swallow{ ( push( L, std::get( tuplen ) ), '\0' )... } ); +} +} // detail + +template +inline void push(lua_State* L, const std::tuple& tuplen) { + detail::push(L, sol::detail::build_indices(), tuplen); +} + +template +inline auto pop_call( lua_State* L, TFx&& fx, types t )->decltype( detail::ltr_pop( L, fx, t ) ) { + return detail::ltr_pop( L, fx, t ); +} + } // stack } // sol diff --git a/sol/state.hpp b/sol/state.hpp index 3489d0cd..a4f154ea 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -1,186 +1,194 @@ -// 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_STATE_HPP -#define SOL_STATE_HPP - -#include "error.hpp" -#include "table.hpp" -#include - -namespace sol { -namespace detail { -template -struct are_same : std::true_type {}; - -template -struct are_same : std::integral_constant::value && are_same::value> {}; - -int atpanic(lua_State* L) { - throw sol_error(lua_tostring(L, -1)); -} -} // detail - -enum class lib : char { - base, - package, - coroutine, - string, - os, - math, - table, - debug, - bit32, - io, - count -}; - -class state { -private: - std::unique_ptr L; - table reg; - table global; -public: - state(): - L(luaL_newstate(), lua_close), - reg(L.get(), LUA_REGISTRYINDEX), - global(reg.get
(LUA_RIDX_GLOBALS)) { - lua_atpanic(L.get(), detail::atpanic); - } - - state(const std::string& filename): - L(luaL_newstate(), lua_close), - reg(L.get(), LUA_REGISTRYINDEX), - global(reg.get
(LUA_RIDX_GLOBALS)) { - lua_atpanic(L.get(), detail::atpanic); - open_file(filename); - } - - template - void open_libraries(Args&&... args) { - static_assert(detail::are_same{}, "all types must be libraries"); - if(sizeof...(args) == 0) { - luaL_openlibs(L.get()); - return; - } - - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - - for(auto&& library : libraries) { - switch(library) { - case lib::base: - luaL_requiref(L.get(), "base", luaopen_base, 1); - break; - case lib::package: - luaL_requiref(L.get(), "package", luaopen_package, 1); - break; - case lib::coroutine: - luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); - break; - case lib::string: - luaL_requiref(L.get(), "string", luaopen_string, 1); - break; - case lib::table: - luaL_requiref(L.get(), "table", luaopen_table, 1); - break; - case lib::math: - luaL_requiref(L.get(), "math", luaopen_math, 1); - break; - case lib::bit32: - luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); - break; - case lib::io: - luaL_requiref(L.get(), "io", luaopen_io, 1); - break; - case lib::os: - luaL_requiref(L.get(), "os", luaopen_os, 1); - break; - case lib::debug: - luaL_requiref(L.get(), "debug", luaopen_debug, 1); - break; - case lib::count: - break; - } - } - } - - void script(const std::string& code) { - if(luaL_dostring(L.get(), code.c_str())) { - lua_error(L.get()); - } - } - - void open_file(const std::string& filename) { - if(luaL_dofile(L.get(), filename.c_str())) { - lua_error(L.get()); - } - } - - template - T get(U&& key) const { - return global.get(std::forward(key)); - } - - template - state& set(T&& key, U&& value) { - global.set(std::forward(key), std::forward(value)); - return *this; - } - - template - table create_table(T&& key, int narr = 0, int nrec = 0) { - if(narr == 0 && nrec == 0) { - lua_newtable(L.get()); - } - else { - lua_createtable(L.get(), narr, nrec); - } - - table result(L.get()); - lua_pop(L.get(), 1); - global.set(std::forward(key), result); - return result; - } - - table create_table(int narr = 0, int nrec = 0) { - if(narr == 0 && nrec == 0) { - lua_newtable(L.get()); - } - else { - lua_createtable(L.get(), narr, nrec); - } - - table result(L.get()); - lua_pop(L.get(), 1); - return result; - } - - table global_table() const { - return global; - } - - table registry() const { - return reg; - } -}; -} // sol - +// 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_STATE_HPP +#define SOL_STATE_HPP + +#include "error.hpp" +#include "table.hpp" +#include + +namespace sol { +namespace detail { +template +struct are_same : std::true_type {}; + +template +struct are_same : std::integral_constant::value && are_same::value> {}; + +int atpanic(lua_State* L) { + throw sol_error(lua_tostring(L, -1)); +} +} // detail + +enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + count +}; + +class state { +private: + std::unique_ptr L; + table reg; + table global; + std::unordered_map> funcs; + +public: + state(): + L(luaL_newstate(), lua_close), + reg(L.get(), LUA_REGISTRYINDEX), + global(reg.get
(LUA_RIDX_GLOBALS)) { + lua_atpanic(L.get(), detail::atpanic); + } + + state(const std::string& filename): + L(luaL_newstate(), lua_close), + reg(L.get(), LUA_REGISTRYINDEX), + global(reg.get
(LUA_RIDX_GLOBALS)) { + lua_atpanic(L.get(), detail::atpanic); + open_file(filename); + } + + template + void open_libraries(Args&&... args) { + static_assert(detail::are_same{}, "all types must be libraries"); + if(sizeof...(args) == 0) { + luaL_openlibs(L.get()); + return; + } + + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; + + for(auto&& library : libraries) { + switch(library) { + case lib::base: + luaL_requiref(L.get(), "base", luaopen_base, 1); + break; + case lib::package: + luaL_requiref(L.get(), "package", luaopen_package, 1); + break; + case lib::coroutine: + luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); + break; + case lib::string: + luaL_requiref(L.get(), "string", luaopen_string, 1); + break; + case lib::table: + luaL_requiref(L.get(), "table", luaopen_table, 1); + break; + case lib::math: + luaL_requiref(L.get(), "math", luaopen_math, 1); + break; + case lib::bit32: + luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); + break; + case lib::io: + luaL_requiref(L.get(), "io", luaopen_io, 1); + break; + case lib::os: + luaL_requiref(L.get(), "os", luaopen_os, 1); + break; + case lib::debug: + luaL_requiref(L.get(), "debug", luaopen_debug, 1); + break; + case lib::count: + break; + } + } + } + + void script(const std::string& code) { + if(luaL_dostring(L.get(), code.c_str())) { + lua_error(L.get()); + } + } + + void open_file(const std::string& filename) { + if(luaL_dofile(L.get(), filename.c_str())) { + lua_error(L.get()); + } + } + + template + T get(U&& key) const { + return global.get(std::forward(key)); + } + + template + state& set(T&& key, U&& value) { + global.set(std::forward(key), std::forward(value)); + return *this; + } + + template + state& set_function( T&& key, TFx&& fx ) { + global.set_function( std::forward( key ), std::forward( fx ) ); + return *this; + } + + template + table create_table(T&& key, int narr = 0, int nrec = 0) { + if(narr == 0 && nrec == 0) { + lua_newtable(L.get()); + } + else { + lua_createtable(L.get(), narr, nrec); + } + + table result(L.get()); + lua_pop(L.get(), 1); + global.set(std::forward(key), result); + return result; + } + + table create_table(int narr = 0, int nrec = 0) { + if(narr == 0 && nrec == 0) { + lua_newtable(L.get()); + } + else { + lua_createtable(L.get(), narr, nrec); + } + + table result(L.get()); + lua_pop(L.get(), 1); + return result; + } + + table global_table() const { + return global; + } + + table registry() const { + return reg; + } +}; +} // sol + #endif // SOL_STATE_HPP \ No newline at end of file diff --git a/sol/table.hpp b/sol/table.hpp index 215ea5a7..97316824 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -23,9 +23,14 @@ #define SOL_TABLE_HPP #include "stack.hpp" +#include "lua_function.hpp" +#include +#include namespace sol { class table : virtual public reference { +private: + std::unordered_map> funcs; public: table() noexcept: reference{} {} table(lua_State* L, int index = -1): reference(L, index) { @@ -53,10 +58,55 @@ public: return *this; } + template + table& set_function( T&& key, TFx&& fx ) { + typedef typename std::remove_pointer::type>::type clean_fx; + const static bool isfunction = std::is_function::value; + return set_function( std::integral_constant( ), + std::forward( key ), std::forward( fx ) ); + } + + template + table& set_function( std::true_type, T&& key, TFx&& fx ) { + typedef typename std::decay::type clean_fx; + std::string fkey( key ); + lua_CFunction freefunc = &detail::lua_cfun; + auto hint = funcs.find( fkey ); + detail::lua_func* target = nullptr; + if ( hint == funcs.end( ) ) { + std::shared_ptr sptr( new detail::lambda_lua_func( std::forward( fx ) ) ); + hint = funcs.emplace_hint( hint, fkey, std::move( sptr ) ); + } + target = hint->second.get( ); + lua_pushlightuserdata( state( ), static_cast( target ) ); + lua_pushcclosure( state( ), freefunc, 1 ); + lua_setglobal( state( ), fkey.c_str( ) ); + return *this; + } + + template + table& set_function( std::false_type, T&& key, TFx&& fx ) { + typedef typename std::decay::type clean_fx; + std::string fkey( key ); + lua_CFunction freefunc = &detail::lua_cfun; + auto hint = funcs.find( fkey ); + detail::lua_func* target = nullptr; + if ( hint == funcs.end( ) ) { + std::shared_ptr sptr( new detail::explicit_lua_func( std::forward( fx ) ) ); + hint = funcs.emplace_hint( hint, fkey, std::move( sptr ) ); + } + target = hint->second.get( ); + lua_pushlightuserdata( state( ), static_cast( target ) ); + lua_pushcclosure( state( ), freefunc, 1 ); + lua_setglobal( state( ), fkey.c_str( ) ); + return *this; + } + size_t size() const { push(); return lua_rawlen(state(), -1); } + }; } // sol diff --git a/sol/tuple.hpp b/sol/tuple.hpp index 60be0bbe..c91d4a7c 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -26,28 +26,25 @@ #include namespace sol { -namespace detail { + template -struct indices {}; +struct indices { }; template -struct build_indices : build_indices {}; +struct build_indices : build_indices { }; template -struct build_indices<0, Ns...> : indices {}; +struct build_indices<0, Ns...> : indices{ }; -using std::get; +template +struct types : build_indices { }; -template -inline auto call(Function f, const Tuple& t, indices) -> decltype(f(get(t)...)) { - return f(get(t)...); -} -} // detail +template +struct tuple_types : types, std::false_type { }; + +template +struct tuple_types> : types, std::true_type{ }; -template -inline auto call(Function f, const std::tuple& t) -> decltype(detail::call(f, t, detail::build_indices{})) { - return call(f, t, detail::build_indices{}); -} } // sol #endif // SOL_TUPLE_HPP \ No newline at end of file diff --git a/sol/types.hpp b/sol/types.hpp index cbc947ef..104d86c4 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -28,7 +28,9 @@ namespace sol { struct nil_t {}; -const nil_t nil{}; +const nil_t nil{ }; +struct Void_t { }; +const Void_t Void{}; enum class type : int { none = LUA_TNONE, From be98a4fdd485f7b3f7af1d32e227f97395b7cadd Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 15:42:03 -0500 Subject: [PATCH 06/11] Reformatted to look like Rapptz's style. The following code sample work without error in VS 2013: http://pastebin.com/s4Jbjnht It'll be up to @Rapptz's to make further changes to make sure GCC compiles, but the core of the functionality is there and my work is essentially done. Class bindings are up next, but really I don't want to even touch those. :c --- sol/function.hpp | 44 ++++++------ sol/functional.hpp | 88 +++++++++++------------ sol/lua_function.hpp | 166 +++++++++++++++++++++---------------------- sol/stack.hpp | 24 +++---- sol/state.hpp | 6 +- sol/table.hpp | 74 +++++++++---------- sol/tuple.hpp | 4 +- 7 files changed, 203 insertions(+), 203 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 059c204b..676b4d77 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -38,34 +38,34 @@ private: template struct invoker { - template - static std::tuple call( const function& ref, Args&&... args ) { - ref.push( ); - ref.push_args( std::forward( args )... ); - lua_pcall( ref.state( ), sizeof...( Args ), sizeof...( Ret ), 0 ); - return std::make_tuple( stack::pop( ref.state( ) )... ); - } + template + static std::tuple call(const function& ref, Args&&... args) { + ref.push(); + ref.push_args(std::forward(args)...); + lua_pcall(ref.state(), sizeof...(Args), sizeof...(Ret), 0); + return std::make_tuple(stack::pop(ref.state())...); + } }; template<> struct invoker<> { - template - static void call( const function& ref, Args&&... args ) { - ref.push( ); - ref.push_args( std::forward( args )... ); - lua_pcall( ref.state( ), sizeof...( Args ), 0, 0 ); - } + template + static void call(const function& ref, Args&&... args) { + ref.push(); + ref.push_args(std::forward(args)...); + lua_pcall(ref.state(), sizeof...(Args), 0, 0); + } }; template struct invoker { - template - static T call( const function& ref, Args&&... args ) { - ref.push( ); - ref.push_args( std::forward( args )... ); - lua_pcall( ref.state( ), sizeof...( Args ), 1, 0 ); - return stack::pop( ref.state( ) ); - } + template + static T call(const function& ref, Args&&... args) { + ref.push(); + ref.push_args(std::forward(args)...); + lua_pcall(ref.state(), sizeof...(Args), 1, 0); + return stack::pop(ref.state()); + } }; public: @@ -75,8 +75,8 @@ public: } template - auto invoke( Args&&... args ) { - return invoker::call( *this, std::forward( args )... ); + auto invoke(Args&&... args) { + return invoker::call(*this, std::forward(args)...); } }; } // sol diff --git a/sol/functional.hpp b/sol/functional.hpp index 349d8d05..7c0e8e34 100644 --- a/sol/functional.hpp +++ b/sol/functional.hpp @@ -31,69 +31,69 @@ template struct function_traits; template -struct function_traits { - static const std::size_t arity = sizeof...( Tn ); - static const bool is_member_function = true; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R( T::* func_t )( Tn... ); - typedef R( T::* func_pointer_t )( Tn... ); - typedef R return_t; - template - using arg_n = std::tuple_element; +struct function_traits { + static const std::size_t arity = sizeof...(Tn); + static const bool is_member_function = true; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R(T::* func_t)(Tn...); + typedef R(T::* func_pointer_t)(Tn...); + typedef R return_t; + template + using arg_n = std::tuple_element; }; template -struct function_traits { - static const std::size_t arity = sizeof...( Tn ); - static const bool is_member_function = true; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R( T::* func_t )( Tn... ); - typedef R( T::* func_pointer_t )( Tn... ); - typedef R return_t; - template - using arg_n = std::tuple_element; +struct function_traits { + static const std::size_t arity = sizeof...(Tn); + static const bool is_member_function = true; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R(T::* func_t)(Tn...); + typedef R(T::* func_pointer_t)(Tn...); + typedef R return_t; + template + using arg_n = std::tuple_element; }; template -struct function_traits { - static const std::size_t arity = sizeof...( Tn ); - static const bool is_member_function = false; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R( func_t )( Tn... ); - typedef R( *func_pointer_t )( Tn... ); - typedef R return_t; - template - using arg_n = std::tuple_element; +struct function_traits { + static const std::size_t arity = sizeof...(Tn); + static const bool is_member_function = false; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R(func_t)(Tn...); + typedef R(*func_pointer_t)(Tn...); + typedef R return_t; + template + using arg_n = std::tuple_element; }; template -struct function_traits { - static const std::size_t arity = sizeof...( Tn ); - static const bool is_member_function = false; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R( func_t )( Tn... ); - typedef R( *func_pointer_t )( Tn... ); - typedef R return_t; - template - using arg_n = std::tuple_element; +struct function_traits { + static const std::size_t arity = sizeof...(Tn); + static const bool is_member_function = false; + typedef std::tuple arg_tuple_t; + typedef types args_t; + typedef R(func_t)(Tn...); + typedef R(*func_pointer_t)(Tn...); + typedef R return_t; + template + using arg_n = std::tuple_element; }; using std::get; template -inline auto call( Function f, const Tuple& t, indices ) -> decltype( f( get( t )... ) ) { - return f( get( t )... ); +inline auto call(Function f, const Tuple& t, indices) -> decltype(f(get(t)...)) { + return f(get(t)...); } } // detail template -inline auto call( Function f, const std::tuple& t ) -> decltype( detail::call( f, t, detail::build_indices{} ) ) { - return call( f, t, detail::build_indices{} ); +inline auto call(Function f, const std::tuple& t) -> decltype(detail::call(f, t, detail::build_indices{})) { + return call(f, t, detail::build_indices{}); } } // sol diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 1d09b0ee..6889cd31 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -28,109 +28,109 @@ namespace sol { namespace detail { - struct lua_func { - virtual int operator () ( lua_State* L ) { - throw sol_error( "Failure to call specialized wrapped C++ function from lua" ); - } +struct lua_func { + virtual int operator () (lua_State* L) { + throw sol_error("Failure to call specialized wrapped C++ function from lua"); + } - virtual ~lua_func( ) {}; - }; + virtual ~lua_func() {}; +}; - template - struct lambda_lua_func : public lua_func { - typedef decltype( &TFx::operator() ) fx_t; - typedef function_traits fx_traits; - TFx fx; +template +struct lambda_lua_func : public lua_func { + typedef decltype(&TFx::operator()) fx_t; + typedef function_traits fx_traits; + TFx fx; - template - lambda_lua_func( TFxn&&... fxn ) : fx( std::forward( fxn )... ) { + template + lambda_lua_func(TFxn&&... fxn) : fx(std::forward(fxn)...) { - } + } - virtual int operator () ( lua_State* L ) override { - return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); - } + virtual int operator () (lua_State* L) override { + return (*this)(tuple_types(), fx_traits::args_t(), L); + } - template - int operator()( types, types t, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - return 0; - } + template + int operator()(types, types t, lua_State* L) { + stack::pop_call(L, fx, t); + return 0; + } - template - int operator()( types, types t, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - stack::push( L, r ); - return sizeof...( TRn ); - } - }; + template + int operator()(types, types t, lua_State* L) { + auto r = stack::pop_call(L, fx, t); + stack::push(L, r); + return sizeof...(TRn); + } +}; - template ::value> - struct explicit_lua_func : public lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; - TFx fx; +template::value> +struct explicit_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type fx_t; + typedef function_traits fx_traits; + TFx fx; - template - explicit_lua_func( TFxn&&... fxn ) : fx( std::forward( fxn )... ) { + template + explicit_lua_func(TFxn&&... fxn) : fx(std::forward(fxn)...) { - } + } - virtual int operator () ( lua_State* L ) override { - return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); - } + virtual int operator () (lua_State* L) override { + return (*this)(tuple_types(), fx_traits::args_t(), L); + } - template - int operator () ( types, types t, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - return 0; - } + template + int operator () (types, types t, lua_State* L) { + stack::pop_call(L, fx, t); + return 0; + } - template - int operator () ( types, types t, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - stack::push( L, r ); - return sizeof...( TRn ); - } - }; + template + int operator () (types, types t, lua_State* L) { + auto r = stack::pop_call(L, fx, t); + stack::push(L, r); + return sizeof...(TRn); + } +}; - template - struct explicit_lua_func : public lua_func { - typedef typename std::remove_pointer::type>::type fx_t; - typedef function_traits fx_traits; - T* member; - TFx fx; - - template - explicit_lua_func( T* m, TFxn&&... fxn ) : member(m), fx( std::forward( fxn )... ) { +template +struct explicit_lua_func : public lua_func { + typedef typename std::remove_pointer::type>::type fx_t; + typedef function_traits fx_traits; + T* member; + TFx fx; + + template + explicit_lua_func(T* m, TFxn&&... fxn) : member(m), fx(std::forward(fxn)...) { - } + } - virtual int operator () ( lua_State* L ) override { - return ( *this )( tuple_types( ), fx_traits::args_t( ), L ); - } + virtual int operator () (lua_State* L) override { + return (*this)(tuple_types(), fx_traits::args_t(), L); + } - template - int operator () ( types, types, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - return 0; - } + template + int operator () (types, types, lua_State* L) { + stack::pop_call(L, fx, t); + return 0; + } - template - int operator () ( types, types t, lua_State* L ) { - auto r = stack::pop_call( L, fx, t ); - stack::push( L, r ); - return sizeof...( TRn ); - } - }; + template + int operator () (types, types t, lua_State* L) { + auto r = stack::pop_call(L, fx, t); + stack::push(L, r); + return sizeof...(TRn); + } +}; - int lua_cfun( lua_State* L ) { - void* bridgedata = lua_touserdata( L, lua_upvalueindex( 1 ) ); - auto* fx = static_cast( bridgedata ); - int r = fx->operator()( L ); - return r; - } +int lua_cfun(lua_State* L) { + void* bridgedata = lua_touserdata(L, lua_upvalueindex(1)); + auto* fx = static_cast(bridgedata); + int r = fx->operator()(L); + return r; +} } // detail } // sol diff --git a/sol/stack.hpp b/sol/stack.hpp index e2863822..b34ba40f 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -37,16 +37,16 @@ using DisableIf = typename std::enable_if::type; namespace stack { namespace detail { template -auto ltr_pop( T&& extra, F f, types<>, Vs&&... vs ) - -> decltype( f( std::forward( vs )... ) ) { - return f( std::forward( vs )... ); +auto ltr_pop(T&& extra, F f, types<>, Vs&&... vs) + -> decltype(f(std::forward(vs)...)) { + return f(std::forward(vs)...); } // take head, produce value from it, pass after other values template -auto ltr_pop( lua_State* L, F f, types, Vs&&... vs ) --> decltype( ltr_pop( L, f, types{}, std::forward( vs )..., stack::pop( L ) ) ) { - return ltr_pop( L, f, types{}, std::forward( vs )..., stack::pop( L ) ); +auto ltr_pop(lua_State* L, F f, types, Vs&&... vs) +-> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., stack::pop(L))) { + return ltr_pop(L, f, types{}, std::forward(vs)..., stack::pop(L)); } template @@ -167,20 +167,20 @@ inline void push(lua_State* L, const std::string& str) { namespace detail { template -inline void push( lua_State* L, indices, const T& tuplen ) { - using swallow = char []; - void( swallow{ ( push( L, std::get( tuplen ) ), '\0' )... } ); +inline void push(lua_State* L, indices, const T& tuplen) { + using swallow = char []; + void(swallow{ '\0', (sol::stack::push(L, std::get(tuplen)), '\0')... }); } } // detail template inline void push(lua_State* L, const std::tuple& tuplen) { - detail::push(L, sol::detail::build_indices(), tuplen); + detail::push(L, build_indices(), tuplen); } template -inline auto pop_call( lua_State* L, TFx&& fx, types t )->decltype( detail::ltr_pop( L, fx, t ) ) { - return detail::ltr_pop( L, fx, t ); +inline auto pop_call(lua_State* L, TFx&& fx, types t)->decltype(detail::ltr_pop(L, fx, t)) { + return detail::ltr_pop(L, fx, t); } } // stack diff --git a/sol/state.hpp b/sol/state.hpp index a4f154ea..0347685d 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -148,9 +148,9 @@ public: } template - state& set_function( T&& key, TFx&& fx ) { - global.set_function( std::forward( key ), std::forward( fx ) ); - return *this; + state& set_function(T&& key, TFx&& fx) { + global.set_function(std::forward(key), std::forward(fx)); + return *this; } template diff --git a/sol/table.hpp b/sol/table.hpp index 97316824..a2090c4f 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -59,54 +59,54 @@ public: } template - table& set_function( T&& key, TFx&& fx ) { - typedef typename std::remove_pointer::type>::type clean_fx; - const static bool isfunction = std::is_function::value; - return set_function( std::integral_constant( ), - std::forward( key ), std::forward( fx ) ); + table& set_function(T&& key, TFx&& fx) { + typedef typename std::remove_pointer::type>::type clean_fx; + const static bool isfunction = std::is_function::value; + return set_function(std::integral_constant(), + std::forward(key), std::forward(fx)); } template - table& set_function( std::true_type, T&& key, TFx&& fx ) { - typedef typename std::decay::type clean_fx; - std::string fkey( key ); - lua_CFunction freefunc = &detail::lua_cfun; - auto hint = funcs.find( fkey ); - detail::lua_func* target = nullptr; - if ( hint == funcs.end( ) ) { - std::shared_ptr sptr( new detail::lambda_lua_func( std::forward( fx ) ) ); - hint = funcs.emplace_hint( hint, fkey, std::move( sptr ) ); - } - target = hint->second.get( ); - lua_pushlightuserdata( state( ), static_cast( target ) ); - lua_pushcclosure( state( ), freefunc, 1 ); - lua_setglobal( state( ), fkey.c_str( ) ); - return *this; + table& set_function(std::true_type, T&& key, TFx&& fx) { + typedef typename std::decay::type clean_fx; + std::string fkey(key); + lua_CFunction freefunc = &detail::lua_cfun; + auto hint = funcs.find(fkey); + detail::lua_func* target = nullptr; + if (hint == funcs.end()) { + std::shared_ptr sptr(new detail::lambda_lua_func(std::forward(fx))); + hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); + } + target = hint->second.get(); + lua_pushlightuserdata(state(), static_cast(target)); + lua_pushcclosure(state(), freefunc, 1); + lua_setglobal(state(), fkey.c_str()); + return *this; } - template - table& set_function( std::false_type, T&& key, TFx&& fx ) { - typedef typename std::decay::type clean_fx; - std::string fkey( key ); - lua_CFunction freefunc = &detail::lua_cfun; - auto hint = funcs.find( fkey ); - detail::lua_func* target = nullptr; - if ( hint == funcs.end( ) ) { - std::shared_ptr sptr( new detail::explicit_lua_func( std::forward( fx ) ) ); - hint = funcs.emplace_hint( hint, fkey, std::move( sptr ) ); - } - target = hint->second.get( ); - lua_pushlightuserdata( state( ), static_cast( target ) ); - lua_pushcclosure( state( ), freefunc, 1 ); - lua_setglobal( state( ), fkey.c_str( ) ); - return *this; + template + table& set_function(std::false_type, T&& key, TFx&& fx) { + typedef typename std::decay::type clean_fx; + std::string fkey(key); + lua_CFunction freefunc = &detail::lua_cfun; + auto hint = funcs.find(fkey); + detail::lua_func* target = nullptr; + if (hint == funcs.end()) { + std::shared_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); + hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); + } + target = hint->second.get(); + lua_pushlightuserdata(state(), static_cast(target)); + lua_pushcclosure(state(), freefunc, 1); + lua_setglobal(state(), fkey.c_str()); + return *this; } size_t size() const { push(); return lua_rawlen(state(), -1); } - + }; } // sol diff --git a/sol/tuple.hpp b/sol/tuple.hpp index c91d4a7c..df119139 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -37,12 +37,12 @@ template struct build_indices<0, Ns...> : indices{ }; template -struct types : build_indices { }; +struct types : build_indices { }; template struct tuple_types : types, std::false_type { }; -template +template struct tuple_types> : types, std::true_type{ }; } // sol From 29f171e124ed8bc70f97256fb7df04c000736431 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 18:11:25 -0500 Subject: [PATCH 07/11] Style fixes and fixes for templates not usually used by MSVC (broken two-phase lookup killing me here. :c) Member functions now work as well for set_function. If performance of `new`ing a type ever becomes too large, we can create a custom allocator for the std::shared_ptr's of the types. We can also up-front allocate for the unordered_map as well. --- sol/functional.hpp | 78 ++++++++++++++++++++-------------------- sol/lua_function.hpp | 65 +++++++++++++++++++++------------- sol/stack.hpp | 4 +-- sol/state.hpp | 10 ++++-- sol/table.hpp | 84 ++++++++++++++++++++++++-------------------- 5 files changed, 135 insertions(+), 106 deletions(-) diff --git a/sol/functional.hpp b/sol/functional.hpp index 7c0e8e34..f16fc528 100644 --- a/sol/functional.hpp +++ b/sol/functional.hpp @@ -30,70 +30,70 @@ namespace detail { template struct function_traits; -template -struct function_traits { - static const std::size_t arity = sizeof...(Tn); +template +struct function_traits { + static const std::size_t arity = sizeof...(Args); static const bool is_member_function = true; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R(T::* func_t)(Tn...); - typedef R(T::* func_pointer_t)(Tn...); - typedef R return_t; + typedef std::tuple arg_tuple_type; + typedef types args_type; + typedef R(T::* func_pointer_type)(Args...); + typedef typename std::remove_pointer::type func_type; + typedef R return_type; template - using arg_n = std::tuple_element; + using arg_n = std::tuple_element; }; -template -struct function_traits { - static const std::size_t arity = sizeof...(Tn); +template +struct function_traits { + static const std::size_t arity = sizeof...(Args); static const bool is_member_function = true; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R(T::* func_t)(Tn...); - typedef R(T::* func_pointer_t)(Tn...); - typedef R return_t; + typedef std::tuple arg_tuple_type; + typedef types args_type; + typedef R(T::* func_type)(Args...); + typedef R(T::* func_pointer_type)(Args...); + typedef R return_type; template - using arg_n = std::tuple_element; + using arg_n = std::tuple_element; }; -template -struct function_traits { - static const std::size_t arity = sizeof...(Tn); +template +struct function_traits { + static const std::size_t arity = sizeof...(Args); static const bool is_member_function = false; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R(func_t)(Tn...); - typedef R(*func_pointer_t)(Tn...); - typedef R return_t; + typedef std::tuple arg_tuple_type; + typedef types args_type; + typedef R(func_type)(Args...); + typedef R(*func_pointer_type)(Args...); + typedef R return_type; template - using arg_n = std::tuple_element; + using arg_n = std::tuple_element; }; -template -struct function_traits { - static const std::size_t arity = sizeof...(Tn); +template +struct function_traits { + static const std::size_t arity = sizeof...(Args); static const bool is_member_function = false; - typedef std::tuple arg_tuple_t; - typedef types args_t; - typedef R(func_t)(Tn...); - typedef R(*func_pointer_t)(Tn...); - typedef R return_t; + typedef std::tuple arg_tuple_type; + typedef types args_type; + typedef R(func_type)(Args...); + typedef R(*func_pointer_type)(Args...); + typedef R return_type; template - using arg_n = std::tuple_element; + using arg_n = std::tuple_element; }; using std::get; template -inline auto call(Function f, const Tuple& t, indices) -> decltype(f(get(t)...)) { +inline auto call(Function&& f, const Tuple& t, indices) -> decltype(f(get(t)...)) { return f(get(t)...); } } // detail template -inline auto call(Function f, const std::tuple& t) -> decltype(detail::call(f, t, detail::build_indices{})) { - return call(f, t, detail::build_indices{}); +inline auto call(Function&& f, const std::tuple& t) -> decltype(detail::call(std::forward(f), t, build_indices{})) { + return call(std::forward(f), t, build_indices{}); } } // sol diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 6889cd31..af9a2cab 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -42,23 +42,23 @@ struct lambda_lua_func : public lua_func { typedef function_traits fx_traits; TFx fx; - template - lambda_lua_func(TFxn&&... fxn) : fx(std::forward(fxn)...) { + template + lambda_lua_func(FxArgs&&... fxargs) : fx(std::forward(fxargs)...) { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_t(), L); + return (*this)(tuple_types(), fx_traits::args_type(), L); } - template - int operator()(types, types t, lua_State* L) { + template + int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator()(types, types t, lua_State* L) { + template + int operator()(types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); stack::push(L, r); return sizeof...(TRn); @@ -71,23 +71,23 @@ struct explicit_lua_func : public lua_func { typedef function_traits fx_traits; TFx fx; - template - explicit_lua_func(TFxn&&... fxn) : fx(std::forward(fxn)...) { + template + explicit_lua_func(FxArgs&&... fxargs) : fx(std::forward(fxargs)...) { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_t(), L); + return (*this)(tuple_types(), fx_traits::args_type(), L); } - template - int operator () (types, types t, lua_State* L) { + template + int operator () (types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator () (types, types t, lua_State* L) { + template + int operator () (types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); stack::push(L, r); return sizeof...(TRn); @@ -98,26 +98,43 @@ template struct explicit_lua_func : public lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; - T* member; - TFx fx; - - template - explicit_lua_func(T* m, TFxn&&... fxn) : member(m), fx(std::forward(fxn)...) { + struct lambda { + T* member; + TFx invocation; + + template + lambda(T* m, FxArgs&&... fxargs) : member(m), invocation(std::forward(fxargs)...) { + + } + + template + typename fx_traits::return_type operator () (Args&&... args) { + return ((*member).*invocation)(std::forward(args)...); + } + } fx; + + template + explicit_lua_func(T* m, FxArgs&&... fxargs) : fx(m, std::forward(fxargs)...) { + + } + + template + explicit_lua_func(T& m, FxArgs&&... fxargs) : fx(std::addressof(m), std::forward(fxargs)...) { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_t(), L); + return (*this)(tuple_types(), fx_traits::args_type(), L); } - template - int operator () (types, types, lua_State* L) { + template + int operator () (types, types, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator () (types, types t, lua_State* L) { + template + int operator () (types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); stack::push(L, r); return sizeof...(TRn); diff --git a/sol/stack.hpp b/sol/stack.hpp index b34ba40f..02c302bd 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -45,8 +45,8 @@ auto ltr_pop(T&& extra, F f, types<>, Vs&&... vs) // take head, produce value from it, pass after other values template auto ltr_pop(lua_State* L, F f, types, Vs&&... vs) --> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., stack::pop(L))) { - return ltr_pop(L, f, types{}, std::forward(vs)..., stack::pop(L)); +-> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., pop(L))) { + return ltr_pop(L, f, types{}, std::forward(vs)..., pop(L)); } template diff --git a/sol/state.hpp b/sol/state.hpp index 0347685d..fc56f4c4 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -149,8 +149,14 @@ public: template state& set_function(T&& key, TFx&& fx) { - global.set_function(std::forward(key), std::forward(fx)); - return *this; + global.set_function(std::forward(key), std::forward(fx)); + return *this; + } + + template + state& set_function(T&& key, TFx&& fx, TM& mem) { + global.set_function(std::forward(key), std::forward(fx), mem); + return *this; } template diff --git a/sol/table.hpp b/sol/table.hpp index a2090c4f..81525579 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -60,53 +60,59 @@ public: template table& set_function(T&& key, TFx&& fx) { - typedef typename std::remove_pointer::type>::type clean_fx; - const static bool isfunction = std::is_function::value; - return set_function(std::integral_constant(), - std::forward(key), std::forward(fx)); + typedef typename std::remove_pointer::type>::type clean_fx; + const static bool isfunction = std::is_function::value; + return set_fx(std::integral_constant(), + std::forward(key), std::forward(fx)); } - template - table& set_function(std::true_type, T&& key, TFx&& fx) { - typedef typename std::decay::type clean_fx; - std::string fkey(key); - lua_CFunction freefunc = &detail::lua_cfun; - auto hint = funcs.find(fkey); - detail::lua_func* target = nullptr; - if (hint == funcs.end()) { - std::shared_ptr sptr(new detail::lambda_lua_func(std::forward(fx))); - hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); - } - target = hint->second.get(); - lua_pushlightuserdata(state(), static_cast(target)); - lua_pushcclosure(state(), freefunc, 1); - lua_setglobal(state(), fkey.c_str()); - return *this; - } - - template - table& set_function(std::false_type, T&& key, TFx&& fx) { - typedef typename std::decay::type clean_fx; - std::string fkey(key); - lua_CFunction freefunc = &detail::lua_cfun; - auto hint = funcs.find(fkey); - detail::lua_func* target = nullptr; - if (hint == funcs.end()) { - std::shared_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); - hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); - } - target = hint->second.get(); - lua_pushlightuserdata(state(), static_cast(target)); - lua_pushcclosure(state(), freefunc, 1); - lua_setglobal(state(), fkey.c_str()); - return *this; + template + table& set_function(T&& key, TFx&& fx, TM& mem) { + typedef typename std::remove_pointer::type>::type clean_fx; + std::unique_ptr sptr(new detail::explicit_lua_func(mem, std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); } size_t size() const { push(); return lua_rawlen(state(), -1); } - + +private: + + template + table& set_fx(std::true_type, T&& key, TFx&& fx) { + typedef typename std::remove_pointer::type>::type clean_fx; + std::unique_ptr sptr(new detail::lambda_lua_func(std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); + } + + template + table& set_fx(std::false_type, T&& key, TFx&& fx) { + typedef typename std::remove_pointer::type>::type clean_fx; + typedef typename std::decay::type ptr_fx; + std::unique_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); + } + + template + table& set_fx(T&& key, std::unique_ptr funcptr) { + std::string fkey(key); + auto hint = funcs.find(fkey); + if (hint == funcs.end()) { + std::shared_ptr sptr(funcptr.release()); + hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); + } + else { + hint->second.reset(funcptr.release()); + } + detail::lua_func* target = target = hint->second.get(); + lua_CFunction freefunc = &detail::lua_cfun; + lua_pushlightuserdata(state(), static_cast(target)); + lua_pushcclosure(state(), freefunc, 1); + lua_setglobal(state(), fkey.c_str()); + return *this; + } }; } // sol From bf2404bdfde393ed079b25f0295b5d8149e0e03b Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 19:15:23 -0500 Subject: [PATCH 08/11] More style fixes and more attempts to make sure this compiles between GCC and MSVC. --- sol/function.hpp | 47 ++++++++++++++++----------- sol/functional.hpp | 20 ++++++++++++ sol/lua_function.hpp | 26 +++++++-------- sol/stack.hpp | 6 ++++ sol/state.hpp | 8 ++--- sol/table.hpp | 76 ++++++++++++++++++++++---------------------- 6 files changed, 110 insertions(+), 73 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 676b4d77..da976d04 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -29,20 +29,12 @@ namespace sol { class function : virtual public reference { private: - template - void push_args(Args&&... args) const { - auto L = state(); - using swallow = char[ ]; - void(swallow{ (stack::push(L, std::forward(args)), '\0')... }); - } template struct invoker { template static std::tuple call(const function& ref, Args&&... args) { - ref.push(); - ref.push_args(std::forward(args)...); - lua_pcall(ref.state(), sizeof...(Args), sizeof...(Ret), 0); + lua_pcall( ref.state( ), sizeof...( Args ), sizeof...( Ret ), 0 ); return std::make_tuple(stack::pop(ref.state())...); } }; @@ -51,9 +43,7 @@ private: struct invoker<> { template static void call(const function& ref, Args&&... args) { - ref.push(); - ref.push_args(std::forward(args)...); - lua_pcall(ref.state(), sizeof...(Args), 0, 0); + lua_pcall( ref.state( ), sizeof...( Args ), 0, 0 ); } }; @@ -61,13 +51,32 @@ private: struct invoker { template static T call(const function& ref, Args&&... args) { - ref.push(); - ref.push_args(std::forward(args)...); - lua_pcall(ref.state(), sizeof...(Args), 1, 0); - return stack::pop(ref.state()); + lua_pcall( ref.state( ), sizeof...( Args ), 1, 0 ); + return stack::pop( ref.state( ) ); + } }; + template + std::tuple invoke( types, std::size_t n ) { + lua_pcall( state( ), n, sizeof...( Ret ), 0 ); + return stack::pop_call( state( ), std::make_tuple, types() ); + } + + template + Ret invoke( types, std::size_t n ) { + lua_pcall( state( ), n, 1, 0 ); + return stack::pop( state( ) ); + } + + void invoke( types, std::size_t n ) { + lua_pcall( state( ), n, 0, 0 ); + } + + void invoke( types<>, std::size_t n ) { + lua_pcall( state( ), n, 0, 0 ); + } + public: function() : reference() {} function(lua_State* L, int index = -1) : reference(L, index) { @@ -75,8 +84,10 @@ public: } template - auto invoke(Args&&... args) { - return invoker::call(*this, std::forward(args)...); + auto invoke(Args&&... args) -> decltype(invoke( types( ), sizeof...( Args ) )) { + push( ); + stack::push_args( state( ), std::forward( args )... ); + return invoke( types( ), sizeof...( Args ) ); } }; } // sol diff --git a/sol/functional.hpp b/sol/functional.hpp index f16fc528..3fe6ae18 100644 --- a/sol/functional.hpp +++ b/sol/functional.hpp @@ -91,6 +91,26 @@ inline auto call(Function&& f, const Tuple& t, indices) -> decltype( } // detail +template +struct lua_return_type { + typedef std::tuple type; +}; + +template +struct lua_return_type { + typedef Ret type; +}; + +template <> +struct lua_return_type<> { + typedef void type; +}; + +template <> +struct lua_return_type { + typedef void type; +}; + template inline auto call(Function&& f, const std::tuple& t) -> decltype(detail::call(std::forward(f), t, build_indices{})) { return call(std::forward(f), t, build_indices{}); diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index af9a2cab..f295030e 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -29,7 +29,7 @@ namespace sol { namespace detail { struct lua_func { - virtual int operator () (lua_State* L) { + virtual int operator () (lua_State*) { throw sol_error("Failure to call specialized wrapped C++ function from lua"); } @@ -48,7 +48,7 @@ struct lambda_lua_func : public lua_func { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_type(), L); + return ( *this )( tuple_types( ), typename fx_traits::args_type( ), L ); } template @@ -77,7 +77,7 @@ struct explicit_lua_func : public lua_func { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_type(), L); + return ( *this )( tuple_types( ), typename fx_traits::args_type( ), L ); } template @@ -99,18 +99,18 @@ struct explicit_lua_func : public lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; struct lambda { - T* member; - TFx invocation; + T* member; + TFx invocation; - template - lambda(T* m, FxArgs&&... fxargs) : member(m), invocation(std::forward(fxargs)...) { + template + lambda(T* m, FxArgs&&... fxargs) : member(m), invocation(std::forward(fxargs)...) { - } + } - template - typename fx_traits::return_type operator () (Args&&... args) { - return ((*member).*invocation)(std::forward(args)...); - } + template + typename fx_traits::return_type operator () (Args&&... args) { + return ((*member).*invocation)(std::forward(args)...); + } } fx; template @@ -124,7 +124,7 @@ struct explicit_lua_func : public lua_func { } virtual int operator () (lua_State* L) override { - return (*this)(tuple_types(), fx_traits::args_type(), L); + return ( *this )( tuple_types( ), typename fx_traits::args_type( ), L ); } template diff --git a/sol/stack.hpp b/sol/stack.hpp index 02c302bd..a1da5ca2 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -183,6 +183,12 @@ inline auto pop_call(lua_State* L, TFx&& fx, types t)->decltype(detail: return detail::ltr_pop(L, fx, t); } +template +void push_args( lua_State* L, Args&&... args ) { + using swallow = char []; + void( swallow{ '\0', ( stack::push( L, std::forward( args ) ), '\0' )... } ); +} + } // stack } // sol diff --git a/sol/state.hpp b/sol/state.hpp index fc56f4c4..f49bf499 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -149,14 +149,14 @@ public: template state& set_function(T&& key, TFx&& fx) { - global.set_function(std::forward(key), std::forward(fx)); - return *this; + global.set_function(std::forward(key), std::forward(fx)); + return *this; } template state& set_function(T&& key, TFx&& fx, TM& mem) { - global.set_function(std::forward(key), std::forward(fx), mem); - return *this; + global.set_function(std::forward(key), std::forward(fx), mem); + return *this; } template diff --git a/sol/table.hpp b/sol/table.hpp index 81525579..9b9d6ab2 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -60,17 +60,17 @@ public: template table& set_function(T&& key, TFx&& fx) { - typedef typename std::remove_pointer::type>::type clean_fx; - const static bool isfunction = std::is_function::value; - return set_fx(std::integral_constant(), - std::forward(key), std::forward(fx)); + typedef typename std::remove_pointer::type>::type clean_fx; + const static bool isfunction = std::is_function::value; + return set_fx(std::integral_constant(), + std::forward(key), std::forward(fx)); } template table& set_function(T&& key, TFx&& fx, TM& mem) { - typedef typename std::remove_pointer::type>::type clean_fx; - std::unique_ptr sptr(new detail::explicit_lua_func(mem, std::forward(fx))); - return set_fx(std::forward(key), std::move(sptr)); + typedef typename std::remove_pointer::type>::type clean_fx; + std::unique_ptr sptr(new detail::explicit_lua_func(mem, std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); } size_t size() const { @@ -80,39 +80,39 @@ public: private: - template - table& set_fx(std::true_type, T&& key, TFx&& fx) { - typedef typename std::remove_pointer::type>::type clean_fx; - std::unique_ptr sptr(new detail::lambda_lua_func(std::forward(fx))); - return set_fx(std::forward(key), std::move(sptr)); - } + template + table& set_fx(std::true_type, T&& key, TFx&& fx) { + typedef typename std::remove_pointer::type>::type clean_fx; + std::unique_ptr sptr(new detail::lambda_lua_func(std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); + } - template - table& set_fx(std::false_type, T&& key, TFx&& fx) { - typedef typename std::remove_pointer::type>::type clean_fx; - typedef typename std::decay::type ptr_fx; - std::unique_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); - return set_fx(std::forward(key), std::move(sptr)); - } + template + table& set_fx(std::false_type, T&& key, TFx&& fx) { + typedef typename std::remove_pointer::type>::type clean_fx; + typedef typename std::decay::type ptr_fx; + std::unique_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); + return set_fx(std::forward(key), std::move(sptr)); + } - template - table& set_fx(T&& key, std::unique_ptr funcptr) { - std::string fkey(key); - auto hint = funcs.find(fkey); - if (hint == funcs.end()) { - std::shared_ptr sptr(funcptr.release()); - hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); - } - else { - hint->second.reset(funcptr.release()); - } - detail::lua_func* target = target = hint->second.get(); - lua_CFunction freefunc = &detail::lua_cfun; - lua_pushlightuserdata(state(), static_cast(target)); - lua_pushcclosure(state(), freefunc, 1); - lua_setglobal(state(), fkey.c_str()); - return *this; - } + template + table& set_fx(T&& key, std::unique_ptr funcptr) { + std::string fkey(key); + auto hint = funcs.find(fkey); + if (hint == funcs.end()) { + std::shared_ptr sptr(funcptr.release()); + hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); + } + else { + hint->second.reset(funcptr.release()); + } + detail::lua_func* target = hint->second.get(); + lua_CFunction freefunc = &detail::lua_cfun; + lua_pushlightuserdata(state(), static_cast(target)); + lua_pushcclosure(state(), freefunc, 1); + lua_setglobal(state(), fkey.c_str()); + return *this; + } }; } // sol From 17ec059c32cdab59740b6e2f2b57ea09769af0ff Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 19:34:10 -0500 Subject: [PATCH 09/11] Move ltr_pop down, so that GCC can see the right instantiations of the functions it needs. --- sol/stack.hpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index a1da5ca2..9fcfb3c4 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -36,19 +36,6 @@ using DisableIf = typename std::enable_if::type; namespace stack { namespace detail { -template -auto ltr_pop(T&& extra, F f, types<>, Vs&&... vs) - -> decltype(f(std::forward(vs)...)) { - return f(std::forward(vs)...); -} - -// take head, produce value from it, pass after other values -template -auto ltr_pop(lua_State* L, F f, types, Vs&&... vs) --> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., pop(L))) { - return ltr_pop(L, f, types{}, std::forward(vs)..., pop(L)); -} - template inline T get_unsigned(lua_State* L, std::true_type, int index = -1) { return lua_tounsigned(L, index); @@ -171,6 +158,20 @@ inline void push(lua_State* L, indices, const T& tuplen) { using swallow = char []; void(swallow{ '\0', (sol::stack::push(L, std::get(tuplen)), '\0')... }); } + +template +auto ltr_pop(T&& extra, F f, types<>, Vs&&... vs) + -> decltype(f(std::forward(vs)...)) { + return f(std::forward(vs)...); +} + +// take head, produce value from it, pass after other values +template +auto ltr_pop(lua_State* L, F f, types, Vs&&... vs) +-> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., pop(L))) { + return ltr_pop(L, f, types{}, std::forward(vs)..., pop(L)); +} + } // detail template From 86b16dc61b924250524f621a17f2e41f5ab45edb Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 20:12:25 -0500 Subject: [PATCH 10/11] GCC is still not compiling, complaining about detail::ltr_pop and not being able to find a proper overload. I'm not sure why it's complaining, I'll have to look in more detail soon. --- sol/function.hpp | 43 +++++++++---------------------------------- sol/lua_function.hpp | 2 +- sol/stack.hpp | 12 ++++++------ sol/table.hpp | 1 - 4 files changed, 16 insertions(+), 42 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index da976d04..d77bf480 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -30,50 +30,25 @@ namespace sol { class function : virtual public reference { private: - template - struct invoker { - template - static std::tuple call(const function& ref, Args&&... args) { - lua_pcall( ref.state( ), sizeof...( Args ), sizeof...( Ret ), 0 ); - return std::make_tuple(stack::pop(ref.state())...); - } - }; - - template<> - struct invoker<> { - template - static void call(const function& ref, Args&&... args) { - lua_pcall( ref.state( ), sizeof...( Args ), 0, 0 ); - } - }; - - template - struct invoker { - template - static T call(const function& ref, Args&&... args) { - lua_pcall( ref.state( ), sizeof...( Args ), 1, 0 ); - return stack::pop( ref.state( ) ); - - } - }; - template - std::tuple invoke( types, std::size_t n ) { + std::tuple call( types, std::size_t n ) { + typedef typename std::decay)>::type maketuple_t; + maketuple_t m = &std::make_tuple; lua_pcall( state( ), n, sizeof...( Ret ), 0 ); - return stack::pop_call( state( ), std::make_tuple, types() ); + return stack::pop_call( state( ), m, types() ); } template - Ret invoke( types, std::size_t n ) { + Ret call( types, std::size_t n ) { lua_pcall( state( ), n, 1, 0 ); return stack::pop( state( ) ); } - void invoke( types, std::size_t n ) { + void call( types, std::size_t n ) { lua_pcall( state( ), n, 0, 0 ); } - void invoke( types<>, std::size_t n ) { + void call( types<>, std::size_t n ) { lua_pcall( state( ), n, 0, 0 ); } @@ -84,10 +59,10 @@ public: } template - auto invoke(Args&&... args) -> decltype(invoke( types( ), sizeof...( Args ) )) { + auto invoke(Args&&... args) -> decltype(call(types( ), sizeof...( Args ))) { push( ); stack::push_args( state( ), std::forward( args )... ); - return invoke( types( ), sizeof...( Args ) ); + return call( types( ), sizeof...( Args ) ); } }; } // sol diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index f295030e..225fda71 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -128,7 +128,7 @@ struct explicit_lua_func : public lua_func { } template - int operator () (types, types, lua_State* L) { + int operator () (types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } diff --git a/sol/stack.hpp b/sol/stack.hpp index 9fcfb3c4..c0d262ba 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -160,16 +160,16 @@ inline void push(lua_State* L, indices, const T& tuplen) { } template -auto ltr_pop(T&& extra, F f, types<>, Vs&&... vs) +auto ltr_pop(T&&, F&& f, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { return f(std::forward(vs)...); } // take head, produce value from it, pass after other values template -auto ltr_pop(lua_State* L, F f, types, Vs&&... vs) --> decltype(ltr_pop(L, f, types{}, std::forward(vs)..., pop(L))) { - return ltr_pop(L, f, types{}, std::forward(vs)..., pop(L)); +auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) +-> decltype(ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L))) { + return ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L)); } } // detail @@ -180,8 +180,8 @@ inline void push(lua_State* L, const std::tuple& tuplen) { } template -inline auto pop_call(lua_State* L, TFx&& fx, types t)->decltype(detail::ltr_pop(L, fx, t)) { - return detail::ltr_pop(L, fx, t); +inline auto pop_call( lua_State* L, TFx&& fx, types )->decltype( detail::ltr_pop( L, std::forward( fx ), types() ) ) { + return detail::ltr_pop( L, std::forward( fx ), types()); } template diff --git a/sol/table.hpp b/sol/table.hpp index 9b9d6ab2..679a817b 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -89,7 +89,6 @@ private: template table& set_fx(std::false_type, T&& key, TFx&& fx) { - typedef typename std::remove_pointer::type>::type clean_fx; typedef typename std::decay::type ptr_fx; std::unique_ptr sptr(new detail::explicit_lua_func(std::forward(fx))); return set_fx(std::forward(key), std::move(sptr)); From 45000177c3f731318cd0c4794095e555343b3d1c Mon Sep 17 00:00:00 2001 From: ThePhD Date: Mon, 2 Dec 2013 21:39:21 -0500 Subject: [PATCH 11/11] Alright, this should fix the GCC build errors! Everything should work as advertised. A Sol for the Mun: go, go! --- sol/function.hpp | 4 +--- sol/stack.hpp | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index d77bf480..f3d87485 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -32,10 +32,8 @@ private: template std::tuple call( types, std::size_t n ) { - typedef typename std::decay)>::type maketuple_t; - maketuple_t m = &std::make_tuple; lua_pcall( state( ), n, sizeof...( Ret ), 0 ); - return stack::pop_call( state( ), m, types() ); + return stack::pop_call( state( ), std::make_tuple, types( ) ); } template diff --git a/sol/stack.hpp b/sol/stack.hpp index c0d262ba..16b019fc 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -159,17 +159,20 @@ inline void push(lua_State* L, indices, const T& tuplen) { void(swallow{ '\0', (sol::stack::push(L, std::get(tuplen)), '\0')... }); } -template -auto ltr_pop(T&&, F&& f, types<>, Vs&&... vs) - -> decltype(f(std::forward(vs)...)) { - return f(std::forward(vs)...); +template +auto ltr_pop( lua_State*, F&& f, types<>, Vs&&... vs ) +-> decltype( f( std::forward( vs )... ) ) { + return f( std::forward( vs )... ); } - -// take head, produce value from it, pass after other values -template -auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) --> decltype(ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L))) { - return ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L)); +template +auto ltr_pop( lua_State* L, F&& f, types, Vs&&... vs ) +-> decltype( ltr_pop( L, std::forward( f ), types<>( ), std::forward( vs )..., pop( L ) ) ) { + return ltr_pop( L, std::forward( f ), types<>( ), std::forward( vs )..., pop( L ) ); +} +template +auto ltr_pop( lua_State* L, F&& f, types, Vs&&... vs ) +-> decltype( ltr_pop( L, std::forward( f ), types( ), std::forward( vs )..., pop( L ) ) ) { + return ltr_pop( L, std::forward( f ), types( ), std::forward( vs )..., pop( L ) ); } } // detail