mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Thanks to LUA_MULTRET, we can have normal function call syntax with sol::function
that doesn't require the user to pass the arguments in directly with .call<Return1, Return2, Return3>( ... )
function result is meant to be transient, and therefore should not be regularly storeable by the user... but there is no way to make a "and you can't have anything but a temporary to this" type, as far as I can tell.
This commit is contained in:
parent
1b8bc7c1e9
commit
219d10b0b4
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -37,3 +37,4 @@ lua-5.3.0/
|
||||||
.vs/
|
.vs/
|
||||||
lua-5.1.5/
|
lua-5.1.5/
|
||||||
luajit-2.0.4/
|
luajit-2.0.4/
|
||||||
|
*.creator.user.*
|
||||||
|
|
|
@ -33,14 +33,52 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
class function_result {
|
||||||
|
private:
|
||||||
|
lua_State* L;
|
||||||
|
int index;
|
||||||
|
int returncount;
|
||||||
|
|
||||||
|
template <typename T, std::size_t I>
|
||||||
|
T get(types<T>, indices<I>) const {
|
||||||
|
return stack::get<T>(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Ret, std::size_t... I>
|
||||||
|
std::tuple<Ret...> get(types<Ret...>, indices<I...>) const {
|
||||||
|
auto r = std::make_tuple(stack::get<Ret>(L, index + I)...);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
function_result() = default;
|
||||||
|
function_result(lua_State* L, int index = -1, int returncount = 0): L(L), index(index), returncount(returncount) {
|
||||||
|
|
||||||
|
}
|
||||||
|
function_result(const function_result&) = default;
|
||||||
|
function_result& operator=(const function_result&) = default;
|
||||||
|
function_result(function_result&&) = default;
|
||||||
|
function_result& operator=(function_result&&) = default;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
operator T () const {
|
||||||
|
auto tr = tuple_types<T>();
|
||||||
|
return get(tr, tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~function_result() {
|
||||||
|
lua_pop(L, returncount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class function : public reference {
|
class function : public reference {
|
||||||
private:
|
private:
|
||||||
void luacall(std::size_t argcount, std::size_t resultcount) const {
|
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const {
|
||||||
lua_call(state(), static_cast<uint32_t>(argcount), static_cast<uint32_t>(resultcount));
|
lua_call(state(), static_cast<int>(argcount), static_cast<int>(resultcount));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t... I, typename... Ret>
|
template<std::size_t... I, typename... Ret>
|
||||||
std::tuple<Ret...> invoke(indices<I...>, types<Ret...>, std::size_t n) const {
|
std::tuple<Ret...> invoke(indices<I...>, types<Ret...>, std::ptrdiff_t n) const {
|
||||||
luacall(n, sizeof...(Ret));
|
luacall(n, sizeof...(Ret));
|
||||||
const int nreturns = static_cast<int>(sizeof...(Ret));
|
const int nreturns = static_cast<int>(sizeof...(Ret));
|
||||||
const int stacksize = lua_gettop(state());
|
const int stacksize = lua_gettop(state());
|
||||||
|
@ -51,19 +89,23 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t I, typename Ret>
|
template<std::size_t I, typename Ret>
|
||||||
Ret invoke(indices<I>, types<Ret>, std::size_t n) const {
|
Ret invoke(indices<I>, types<Ret>, std::ptrdiff_t n) const {
|
||||||
luacall(n, 1);
|
luacall(n, 1);
|
||||||
return stack::pop<Ret>(state());
|
return stack::pop<Ret>(state());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t I>
|
template <std::size_t I>
|
||||||
void invoke(indices<I>, types<void>, std::size_t n) const {
|
void invoke(indices<I>, types<void>, std::ptrdiff_t n) const {
|
||||||
luacall(n, 0);
|
luacall(n, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void invoke(indices<>, types<>, std::size_t n) const {
|
function_result invoke(indices<>, types<>, std::ptrdiff_t n) const {
|
||||||
auto tr = types<void>();
|
const int stacksize = lua_gettop(state());
|
||||||
invoke(tr, tr, n);
|
const int firstreturn = std::max(0, stacksize - static_cast<int>(n) - 1);
|
||||||
|
luacall(n, LUA_MULTRET);
|
||||||
|
const int poststacksize = lua_gettop(state());
|
||||||
|
const int returncount = poststacksize - firstreturn;
|
||||||
|
return function_result(state(), firstreturn + 1, returncount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -75,8 +117,8 @@ public:
|
||||||
function& operator=(const function&) = default;
|
function& operator=(const function&) = default;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void operator()(Args&&... args) const {
|
function_result operator()(Args&&... args) const {
|
||||||
call<>(std::forward<Args>(args)...);
|
return call<>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Ret, typename... Args>
|
template<typename... Ret, typename... Args>
|
||||||
|
@ -85,7 +127,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Ret, typename... Args>
|
template<typename... Ret, typename... Args>
|
||||||
ReturnType<Ret...> call(Args&&... args) const {
|
auto call(Args&&... args) const -> decltype(invoke(types<Ret...>(), types<Ret...>(), 0)) {
|
||||||
push();
|
push();
|
||||||
int pushcount = stack::push_args(state(), std::forward<Args>(args)...);
|
int pushcount = stack::push_args(state(), std::forward<Args>(args)...);
|
||||||
auto tr = types<Ret...>();
|
auto tr = types<Ret...>();
|
||||||
|
|
|
@ -113,9 +113,9 @@ inline int push_args(lua_State* L, T&& t, Args&&... args) {
|
||||||
return pushcount;
|
return pushcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U = Unqualified<T>>
|
template<typename T>
|
||||||
inline auto get(lua_State* L, int index = -1) -> decltype(getter<U>{}.get(L, index)) {
|
inline auto get(lua_State* L, int index = -1) -> decltype(getter<Unqualified<T>>{}.get(L, index)) {
|
||||||
return getter<U>{}.get(L, index);
|
return getter<Unqualified<T>>{}.get(L, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -619,7 +619,7 @@ inline void call(lua_State* L, types<void> tr, types<Args...> ta, Fx&& fx, FxArg
|
||||||
}
|
}
|
||||||
|
|
||||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
|
inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
|
||||||
if (get<type>(L, 1) == type::table) {
|
if (sol::stack::get<type>(L, 1) == type::table) {
|
||||||
if (luaL_newmetatable(L, meta.c_str()) == 0) {
|
if (luaL_newmetatable(L, meta.c_str()) == 0) {
|
||||||
lua_settop(L, -2);
|
lua_settop(L, -2);
|
||||||
return call_syntax::colon;
|
return call_syntax::colon;
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace sol {
|
||||||
class table : public reference {
|
class table : public reference {
|
||||||
friend class state;
|
friend class state;
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
typename stack::get_return<T>::type single_get(U&& key) const {
|
auto single_get(U&& key) const -> decltype(stack::get<T>(nullptr, 0)) {
|
||||||
push();
|
push();
|
||||||
stack::push(state(), std::forward<U>(key));
|
stack::push(state(), std::forward<U>(key));
|
||||||
lua_gettable(state(), -2);
|
lua_gettable(state(), -2);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user