mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Merge pull request #10 from ThePhD/master
Multi-gets and GCC/VC++ Compatiability again
This commit is contained in:
commit
5b505dcaad
|
@ -35,8 +35,8 @@ private:
|
|||
|
||||
template<typename... Ret>
|
||||
std::tuple<Ret...> invoke(types<Ret...>, std::size_t n) {
|
||||
luacall(n, sizeof...(Ret));
|
||||
return stack::pop_call(state(), std::make_tuple<Ret...>, types<Ret...>());
|
||||
luacall(n, sizeof...(Ret));
|
||||
return stack::pop_reverse_call(state(), std::make_tuple<Ret...>, types<Ret...>());
|
||||
}
|
||||
|
||||
template<typename Ret>
|
||||
|
|
|
@ -62,18 +62,24 @@ template<typename TFx>
|
|||
struct static_lua_func {
|
||||
typedef typename std::remove_pointer<typename std::decay<TFx>::type>::type fx_t;
|
||||
typedef function_traits<fx_t> fx_traits;
|
||||
|
||||
|
||||
template<typename... Args>
|
||||
static int typed_call(types<void>, types<Args...> t, fx_t* fx, lua_State* L) {
|
||||
stack::pop_call(L, fx, t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename... TRn, typename... Args>
|
||||
static int typed_call(types<TRn...>, types<Args...> t, fx_t* fx, lua_State* L) {
|
||||
auto r = stack::pop_call(L, fx, t);
|
||||
template<typename... Args>
|
||||
static int typed_call(types<>, types<Args...> t, fx_t* fx, lua_State* L) {
|
||||
return typed_call(types<void>(), t, fx, L);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
static int typed_call(types<Ret...>, types<Args...> t, fx_t* fx, lua_State* L) {
|
||||
typedef typename multi_return<Ret...>::type return_type;
|
||||
return_type r = stack::pop_call(L, fx, t);
|
||||
stack::push(L, std::move(r));
|
||||
return sizeof...(TRn);
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
static int call(lua_State* L) {
|
||||
|
@ -101,22 +107,18 @@ struct static_object_lua_func {
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename TR, typename... Args>
|
||||
static int typed_call(types<TR>, types<Args...>, T& item, fx_t& ifx, lua_State* L) {
|
||||
auto fx = [&item, &ifx](Args&&... args) -> TR {
|
||||
return (item.*ifx)(std::forward<Args>(args)...);
|
||||
};
|
||||
auto r = stack::pop_call(L, fx, types<Args...>());
|
||||
stack::push(L, std::move(r));
|
||||
return 1;
|
||||
template<typename... Args>
|
||||
static int typed_call(types<>, types<Args...> t, T& item, fx_t& ifx, lua_State* L) {
|
||||
return typed_call(types<void>(), t, item, ifx, L);
|
||||
}
|
||||
|
||||
template<typename... TRn, typename... Args>
|
||||
static int typed_call(types<TRn...>, types<Args...>, T& item, fx_t& ifx, lua_State* L) {
|
||||
auto fx = [&item, &ifx](Args&&... args) -> std::tuple<TRn...> { return (item.*ifx)(std::forward<Args>(args)...); };
|
||||
auto r = stack::pop_call(L, fx, types<Args...>());
|
||||
template<typename... Ret, typename... Args>
|
||||
static int typed_call(types<Ret...>, types<Args...>, T& item, fx_t& ifx, lua_State* L) {
|
||||
typedef typename multi_return<Ret...>::type return_type;
|
||||
auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward<Args>(args)...); };
|
||||
return_type r = stack::pop_call(L, fx, types<Args...>());
|
||||
stack::push(L, std::move(r));
|
||||
return sizeof...(TRn);
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
static int call(lua_State* L) {
|
||||
|
@ -188,11 +190,17 @@ struct lambda_lua_func : public lua_func {
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename... TRn, typename... Args>
|
||||
int operator()(types<TRn...>, types<Args...> t, lua_State* L) {
|
||||
auto r = stack::pop_call(L, fx, t);
|
||||
template<typename... Args>
|
||||
int operator()(types<>, types<Args...> t, lua_State* L) {
|
||||
return (*this)(types<void>(), t, L);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
int operator()(types<Ret...>, types<Args...> t, lua_State* L) {
|
||||
typedef typename multi_return<Ret...>::type return_type;
|
||||
return_type r = stack::pop_call(L, fx, t);
|
||||
stack::push(L, r);
|
||||
return sizeof...(TRn);
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,21 +213,27 @@ struct explicit_lua_func : public lua_func {
|
|||
template<typename... FxArgs>
|
||||
explicit_lua_func(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
return (*this)(tuple_types<typename fx_traits::return_type>(), typename fx_traits::args_type(), L);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
int operator()(types<void>, types<Args...> t, lua_State* L) {
|
||||
stack::pop_call(L, fx, t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename... TRn, typename... Args>
|
||||
int operator()(types<TRn...>, types<Args...> t, lua_State* L) {
|
||||
auto r = stack::pop_call(L, fx, t);
|
||||
template<typename... Args>
|
||||
int operator()(types<>, types<Args...> t, lua_State* L) {
|
||||
return (*this)(types<void>(), t, L);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
int operator()(types<Ret...>, types<Args...> t, lua_State* L) {
|
||||
typedef typename multi_return<Ret...>::type return_type;
|
||||
return_type r = stack::pop_call(L, fx, t);
|
||||
stack::push(L, std::move(r));
|
||||
return sizeof...(TRn);
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
return (*this)(tuple_types<typename fx_traits::return_type>(), typename fx_traits::args_type(), L);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -243,21 +257,27 @@ struct explicit_lua_func<TFx, T, true> : public lua_func {
|
|||
template<typename... FxArgs>
|
||||
explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward<FxArgs>(fxargs)...) {}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
return (*this)(tuple_types<typename fx_traits::return_type>(), typename fx_traits::args_type(), L);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
int operator()(types<void>, types<Args...> t, lua_State* L) {
|
||||
stack::pop_call(L, fx, t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename... TRn, typename... Args>
|
||||
int operator()(types<TRn...>, types<Args...> t, lua_State* L) {
|
||||
auto r = stack::pop_call(L, fx, t);
|
||||
stack::push(L, r);
|
||||
return sizeof...(TRn);
|
||||
template<typename... Args>
|
||||
int operator()(types<>, types<Args...> t, lua_State* L) {
|
||||
return (*this)(types<void>(), t, L);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
int operator()(types<Ret...>, types<Args...> t, lua_State* L) {
|
||||
typedef typename multi_return<Ret...>::type return_type;
|
||||
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::return_type>(), typename fx_traits::args_type(), L);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -212,33 +212,58 @@ inline void push_tuple(lua_State* L, indices<I...>, T&& tuplen) {
|
|||
swallow {'\0', (sol::stack::push(L, std::get<I>(tuplen)), '\0')... };
|
||||
}
|
||||
|
||||
template<typename F, typename... Vs>
|
||||
auto ltr_pop(lua_State*, F&& f, types<>, Vs&&... vs) -> decltype(f(std::forward<Vs>(vs)...)) {
|
||||
template<typename F, typename... Vs, typename... Args>
|
||||
auto ltr_pop(lua_State*, F&& f, types<Args...>, types<>, Vs&&... vs) -> decltype(f(std::forward<Vs>(vs)...)) {
|
||||
return f(std::forward<Vs>(vs)...);
|
||||
}
|
||||
template<typename F, typename Head, typename... Vs>
|
||||
auto ltr_pop(lua_State* L, F&& f, types<Head>, Vs&&... vs) -> decltype(ltr_pop(L, std::forward<F>(f), types<>(), std::forward<Vs>(vs)..., pop<Head>(L))) {
|
||||
return ltr_pop(L, std::forward<F>(f), types<>(), std::forward<Vs>(vs)..., pop<Head>(L));
|
||||
template<typename F, typename Head, typename... Tail, typename... Vs, typename... Args>
|
||||
auto ltr_pop(lua_State* L, F&& f, types<Args...> t, types<Head, Tail...>, Vs&&... vs) -> decltype(f(std::declval<Args>()...)) {
|
||||
return ltr_pop(L, std::forward<F>(f), t, types<Tail...>(), std::forward<Vs>(vs)..., pop<Head>(L));
|
||||
}
|
||||
template<typename F, typename Head, typename... Tail, typename... Vs>
|
||||
auto ltr_pop(lua_State* L, F&& f, types<Head, Tail...>, Vs&&... vs) -> decltype(f(std::forward<Vs>(vs)..., std::declval<Head>(), std::declval<Tail>()...)) {
|
||||
return ltr_pop(L, std::forward<F>(f), types<Tail...>(), std::forward<Vs>(vs)..., pop<Head>(L));
|
||||
|
||||
template<typename F, typename... Vs, typename... Args>
|
||||
auto rtl_pop(lua_State*, F&& f, types<Args...>, types<>, Vs&&... vs) -> decltype(f(std::forward<Vs>(vs)...)) {
|
||||
return f(std::forward<Vs>(vs)...);
|
||||
}
|
||||
template<typename F, typename Head, typename... Tail, typename... Vs, typename... Args>
|
||||
auto rtl_pop(lua_State* L, F&& f, types<Args...> t, types<Head, Tail...>, Vs&&... vs) -> decltype(f(std::declval<Args>()...)) {
|
||||
return rtl_pop(L, std::forward<F>(f), t, types<Tail...>(), pop<Head>(L), std::forward<Vs>(vs)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename... Args>
|
||||
inline void push(lua_State* L, const std::tuple<Args...>& tuplen) {
|
||||
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), tuplen);
|
||||
detail::push_tuple(L, build_indices<sizeof...(Args)>(), tuplen);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void push(lua_State* L, std::tuple<Args...>&& tuplen) {
|
||||
detail::push_tuple(L, build_indices<sizeof...(Args)>(), std::move(tuplen));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void push_reverse(lua_State* L, T&& item) {
|
||||
push(L, std::forward<T>(item));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void push_reverse(lua_State* L, const std::tuple<Args...>& tuplen) {
|
||||
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), tuplen);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void push_reverse(lua_State* L, std::tuple<Args...>&& tuplen) {
|
||||
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), std::move(tuplen));
|
||||
}
|
||||
|
||||
template<typename... Args, typename TFx>
|
||||
inline auto pop_call(lua_State* L, TFx&& fx, types<Args...>) -> decltype(detail::ltr_pop(L, std::forward<TFx>(fx), types<Args...>())) {
|
||||
return detail::ltr_pop(L, std::forward<TFx>(fx), types<Args...>());
|
||||
inline auto pop_call(lua_State* L, TFx&& fx, types<Args...> t) -> decltype(detail::ltr_pop(L, std::forward<TFx>(fx), t, t)) {
|
||||
return detail::ltr_pop(L, std::forward<TFx>(fx), t, t);
|
||||
}
|
||||
|
||||
template<typename... Args, typename TFx>
|
||||
inline auto pop_reverse_call(lua_State* L, TFx&& fx, types<Args...> t) -> decltype(detail::rtl_pop(L, std::forward<TFx>(fx), t, reversed<Args...>())) {
|
||||
return detail::rtl_pop(L, std::forward<TFx>(fx), t, reversed<Args...>());
|
||||
}
|
||||
|
||||
void push_args(lua_State*) {
|
||||
|
|
|
@ -127,9 +127,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T get(U&& key) const {
|
||||
return global.get<T>(std::forward<U>(key));
|
||||
template<typename... Args, typename... Keys>
|
||||
typename multi_return<Args...>::type get(Keys&&... keys) const {
|
||||
return global.get(types<Args...>(), std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
|
|
|
@ -41,15 +41,11 @@ T* get_ptr(T* val) {
|
|||
} // detail
|
||||
|
||||
class table : public reference {
|
||||
friend class state;
|
||||
template<typename Table, typename T> struct proxy;
|
||||
public:
|
||||
table() noexcept : reference() {}
|
||||
table(lua_State* L, int index = -1) : reference(L, index) {
|
||||
type_assert(L, index, type::table);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T get(U&& key) const {
|
||||
T single_get(U&& key) const {
|
||||
push();
|
||||
stack::push(state(), std::forward<U>(key));
|
||||
lua_gettable(state(), -2);
|
||||
|
@ -59,6 +55,44 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
template<std::size_t I, typename Tup, typename... Ret>
|
||||
typename std::tuple_element<I, std::tuple<Ret...>>::type element_get(types<Ret...>, Tup&& key) const {
|
||||
typedef typename std::tuple_element<I, std::tuple<Ret...>>::type T;
|
||||
push();
|
||||
stack::push(state(), std::get<I>(key));
|
||||
lua_gettable(state(), -2);
|
||||
type_assert(state(), -1, type_of<T>());
|
||||
T result = stack::pop<T>(state());
|
||||
lua_pop(state(), 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Tup, typename... Ret, std::size_t... I>
|
||||
typename multi_return<Ret...>::type tuple_get(types<Ret...> t, indices<I...>, Tup&& tup) const {
|
||||
return std::make_tuple(element_get<I>(t, std::forward<Tup>(tup))...);
|
||||
}
|
||||
|
||||
template<typename Tup, typename Ret>
|
||||
Ret tuple_get(types<Ret> t, indices<0>, Tup&& tup) const {
|
||||
return element_get<0>(t, std::forward<Tup>(tup));
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Keys>
|
||||
typename multi_return<Ret...>::type get(types<Ret...> t, Keys&&... keys) const {
|
||||
static_assert(sizeof...(Keys) == sizeof...(Ret), "Must have same number of keys as return values");
|
||||
return tuple_get(t, t, std::make_tuple(std::forward<Keys>(keys)...));
|
||||
}
|
||||
public:
|
||||
table() noexcept : reference() {}
|
||||
table(lua_State* L, int index = -1) : reference(L, index) {
|
||||
type_assert(L, index, type::table);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Keys>
|
||||
typename multi_return<Ret...>::type get(Keys&&... keys) const {
|
||||
return get(types<Ret...>(), std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
table& set(T&& key, U&& value) {
|
||||
push();
|
||||
|
|
|
@ -57,7 +57,16 @@ template<size_t... Ns>
|
|||
struct build_reverse_indices<0, Ns...> : indices<Ns...> {};
|
||||
|
||||
template<typename... Args>
|
||||
struct types : build_indices<sizeof...(Args)> {};
|
||||
struct types : build_indices<sizeof...(Args)> { typedef types type; };
|
||||
|
||||
template<class Acc, class... Args>
|
||||
struct reversed_ : Acc{};
|
||||
|
||||
template<typename... RArgs, typename Arg, typename... Args>
|
||||
struct reversed_<types<RArgs...>, Arg, Args...> : reversed_<types<Arg, RArgs...>, Args...>{};
|
||||
|
||||
template<typename... Args>
|
||||
struct reversed : reversed_<types<>, Args...>{};
|
||||
|
||||
template<typename... Args>
|
||||
struct tuple_types : types<Args...>, std::false_type {};
|
||||
|
|
18
tests.cpp
18
tests.cpp
|
@ -220,6 +220,24 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work
|
|||
REQUIRE_NOTHROW(run_script(lua));
|
||||
}
|
||||
|
||||
TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in the same reading order specified in Lua" ) {
|
||||
const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
|
||||
sol::state lua;
|
||||
lua.set_function( "f", [ ] {
|
||||
return std::make_tuple( 10, 11, 12 );
|
||||
} );
|
||||
lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
|
||||
auto tcpp = lua.get<sol::function>("f").call<int, int, int>();
|
||||
auto tlua = lua.get<sol::function>("g").call<int, int, int>();
|
||||
auto tluaget = lua.get<int, int, int>("x", "y", "z");
|
||||
std::cout << "cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp) << std::endl;
|
||||
std::cout << "lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua) << std::endl;
|
||||
std::cout << "lua.xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z") << std::endl;
|
||||
REQUIRE(tcpp == triple);
|
||||
REQUIRE(tlua == triple);
|
||||
REQUIRE(tluaget == triple);
|
||||
}
|
||||
|
||||
TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
|
Loading…
Reference in New Issue
Block a user