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/
|
||||
lua-5.1.5/
|
||||
luajit-2.0.4/
|
||||
*.creator.user.*
|
||||
|
|
|
@ -33,14 +33,52 @@
|
|||
#include <memory>
|
||||
|
||||
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 {
|
||||
private:
|
||||
void luacall(std::size_t argcount, std::size_t resultcount) const {
|
||||
lua_call(state(), static_cast<uint32_t>(argcount), static_cast<uint32_t>(resultcount));
|
||||
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const {
|
||||
lua_call(state(), static_cast<int>(argcount), static_cast<int>(resultcount));
|
||||
}
|
||||
|
||||
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));
|
||||
const int nreturns = static_cast<int>(sizeof...(Ret));
|
||||
const int stacksize = lua_gettop(state());
|
||||
|
@ -51,19 +89,23 @@ private:
|
|||
}
|
||||
|
||||
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);
|
||||
return stack::pop<Ret>(state());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void invoke(indices<>, types<>, std::size_t n) const {
|
||||
auto tr = types<void>();
|
||||
invoke(tr, tr, n);
|
||||
function_result invoke(indices<>, types<>, std::ptrdiff_t n) const {
|
||||
const int stacksize = lua_gettop(state());
|
||||
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:
|
||||
|
@ -75,8 +117,8 @@ public:
|
|||
function& operator=(const function&) = default;
|
||||
|
||||
template<typename... Args>
|
||||
void operator()(Args&&... args) const {
|
||||
call<>(std::forward<Args>(args)...);
|
||||
function_result operator()(Args&&... args) const {
|
||||
return call<>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
|
@ -85,7 +127,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename... Ret, typename... Args>
|
||||
ReturnType<Ret...> call(Args&&... args) const {
|
||||
auto call(Args&&... args) const -> decltype(invoke(types<Ret...>(), types<Ret...>(), 0)) {
|
||||
push();
|
||||
int pushcount = stack::push_args(state(), std::forward<Args>(args)...);
|
||||
auto tr = types<Ret...>();
|
||||
|
|
|
@ -113,9 +113,9 @@ inline int push_args(lua_State* L, T&& t, Args&&... args) {
|
|||
return pushcount;
|
||||
}
|
||||
|
||||
template<typename T, typename U = Unqualified<T>>
|
||||
inline auto get(lua_State* L, int index = -1) -> decltype(getter<U>{}.get(L, index)) {
|
||||
return getter<U>{}.get(L, index);
|
||||
template<typename T>
|
||||
inline auto get(lua_State* L, int index = -1) -> decltype(getter<Unqualified<T>>{}.get(L, index)) {
|
||||
return getter<Unqualified<T>>{}.get(L, index);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (get<type>(L, 1) == type::table) {
|
||||
if (sol::stack::get<type>(L, 1) == type::table) {
|
||||
if (luaL_newmetatable(L, meta.c_str()) == 0) {
|
||||
lua_settop(L, -2);
|
||||
return call_syntax::colon;
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace sol {
|
|||
class table : public reference {
|
||||
friend class state;
|
||||
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();
|
||||
stack::push(state(), std::forward<U>(key));
|
||||
lua_gettable(state(), -2);
|
||||
|
|
Loading…
Reference in New Issue
Block a user