mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
SPEED AND FIXES, HOOOOOOOOO!
This commit is contained in:
parent
295b7b1a08
commit
e1241c110a
|
@ -189,17 +189,9 @@ inheritance
|
|||
|
||||
Sol can adjust pointers from derived classes to base classes at runtime, but it has some caveats based on what you compile with:
|
||||
|
||||
.. _exceptions_enabled:
|
||||
If your class has no complicated™ virtual inheritance or multiple inheritance, than you can try to sneak away with the performance boost from not specifying any base classes and doing any casting checks. (What does "complicated™" mean? Ask your compiler's documentation, if you're in that deep.)
|
||||
|
||||
**With Exceptions Enabled**
|
||||
|
||||
You do not need to manually specify the base classes. We use a technique that infinitely scales and automatically casts derived pointers to their base classes by exploiting the necessity of exception type matching.
|
||||
|
||||
.. _exceptions_disabled:
|
||||
|
||||
**With Exceptions Disabled**
|
||||
|
||||
You must specify the ``sol::base_classes`` tag with the ``sol::bases<Types...>()`` argument, where ``Types...`` are all the base classes of the single type ``T`` that you are making a usertype out of. If you turn exceptions off and are also completely mad and turn off :doc:`run-time type information<../rtti>` as well, we fallback to a id-based systemthat still requires you to specifically list the base classes as well. For example:
|
||||
For the rest of us safe individuals out there: You must specify the ``sol::base_classes`` tag with the ``sol::bases<Types...>()`` argument, where ``Types...`` are all the base classes of the single type ``T`` that you are making a usertype out of. If you turn exceptions off and are also completely mad and turn off :doc:`run-time type information<../rtti>` as well, we fallback to a id-based systemthat still requires you to specifically list the base classes as well. For example:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
|
22
sol/call.hpp
22
sol/call.hpp
|
@ -145,7 +145,7 @@ namespace call_detail {
|
|||
|
||||
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
static int var_call(std::true_type, lua_State* L, F f) {
|
||||
static int var_call(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
|
@ -153,7 +153,7 @@ namespace call_detail {
|
|||
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f);
|
||||
}
|
||||
|
||||
static int var_call(std::false_type, lua_State* L, F f) {
|
||||
static int var_call(std::false_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
|
@ -161,14 +161,14 @@ namespace call_detail {
|
|||
return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
static int call(lua_State* L, F& f) {
|
||||
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, bool is_index, bool is_variable>
|
||||
struct agnostic_lua_call_wrapper<F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||
static int call(lua_State* L, F f) {
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::args_list args_list;
|
||||
|
@ -204,7 +204,7 @@ namespace call_detail {
|
|||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_prop) {
|
||||
static int call(lua_State* L, no_prop&) {
|
||||
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
|
||||
}
|
||||
};
|
||||
|
@ -213,7 +213,7 @@ namespace call_detail {
|
|||
struct agnostic_lua_call_wrapper<F, false, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call_assign(std::true_type, lua_State* L, F f) {
|
||||
static int call_assign(std::true_type, lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::object_type object_type;
|
||||
|
@ -233,20 +233,20 @@ namespace call_detail {
|
|||
#endif // Safety
|
||||
}
|
||||
|
||||
static int call_assign(std::false_type, lua_State* L, F) {
|
||||
static int call_assign(std::false_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
static int call_const(std::false_type, lua_State* L, F f) {
|
||||
static int call_const(std::false_type, lua_State* L, F& f) {
|
||||
typedef typename traits_type::return_type R;
|
||||
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
|
||||
}
|
||||
|
||||
static int call_const(std::true_type, lua_State* L, F) {
|
||||
static int call_const(std::true_type, lua_State* L, F&) {
|
||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
static int call(lua_State* L, F& f) {
|
||||
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
|
||||
}
|
||||
};
|
||||
|
@ -255,7 +255,7 @@ namespace call_detail {
|
|||
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||
typedef sol::lua_bind_traits<F> traits_type;
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
static int call(lua_State* L, F& f) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
|
|
|
@ -89,7 +89,7 @@ struct pusher<function_sig<Sigs...>> {
|
|||
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ struct pusher<function_sig<Sigs...>> {
|
|||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ static void func_gc(std::true_type, lua_State*) {
|
|||
template <std::size_t limit>
|
||||
static void func_gc(std::false_type, lua_State* L) {
|
||||
for (std::size_t i = 0; i < limit; ++i) {
|
||||
void* value = stack::get<light_userdata_value>(L, up_value_index(static_cast<int>(i + 1)));
|
||||
void* value = stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(i + 1)));
|
||||
if (value == nullptr)
|
||||
continue;
|
||||
base_function* obj = static_cast<base_function*>(value);
|
||||
|
@ -81,7 +81,7 @@ static void func_gc(std::false_type, lua_State* L) {
|
|||
}
|
||||
|
||||
inline int call(lua_State* L) {
|
||||
void* ludata = stack::get<light_userdata_value>(L, up_value_index(1));
|
||||
void* ludata = stack::get<lightuserdata_value>(L, up_value_index(1));
|
||||
void** pinheritancedata = static_cast<void**>(ludata);
|
||||
return base_call(L, *pinheritancedata);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ inline int gc(lua_State* L) {
|
|||
template<std::size_t I>
|
||||
inline int usertype_call(lua_State* L) {
|
||||
// Zero-based template parameter, but upvalues start at 1
|
||||
return base_call(L, stack::get<light_userdata_value>(L, up_value_index(static_cast<int>(I + 1))));
|
||||
return base_call(L, stack::get<lightuserdata_value>(L, up_value_index(static_cast<int>(I + 1))));
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
|
|
272
sol/stack.hpp
272
sol/stack.hpp
|
@ -34,171 +34,169 @@
|
|||
#include <cstring>
|
||||
#include <array>
|
||||
|
||||
namespace sol {
|
||||
namespace stack {
|
||||
namespace stack_detail {
|
||||
template <typename T>
|
||||
struct is_this_state_raw : std::false_type {};
|
||||
template <>
|
||||
struct is_this_state_raw<this_state> : std::true_type {};
|
||||
template <typename T>
|
||||
using is_this_state = is_this_state_raw<meta::unqualified_t<T>>;
|
||||
namespace sol { namespace stack {
|
||||
namespace stack_detail {
|
||||
template <typename T>
|
||||
struct is_this_state_raw : std::false_type {};
|
||||
template <>
|
||||
struct is_this_state_raw<this_state> : std::true_type {};
|
||||
template <typename T>
|
||||
using is_this_state = is_this_state_raw<meta::unqualified_t<T>>;
|
||||
|
||||
template<typename T>
|
||||
inline int push_as_upvalues(lua_State* L, T& item) {
|
||||
typedef std::decay_t<T> TValue;
|
||||
const static std::size_t itemsize = sizeof(TValue);
|
||||
const static std::size_t voidsize = sizeof(void*);
|
||||
const static std::size_t voidsizem1 = voidsize - 1;
|
||||
const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
template<typename T>
|
||||
inline int push_as_upvalues(lua_State* L, T& item) {
|
||||
typedef std::decay_t<T> TValue;
|
||||
const static std::size_t itemsize = sizeof(TValue);
|
||||
const static std::size_t voidsize = sizeof(void*);
|
||||
const static std::size_t voidsizem1 = voidsize - 1;
|
||||
const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
|
||||
data_t data{{}};
|
||||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||
int pushcount = 0;
|
||||
for(auto&& v : data) {
|
||||
pushcount += push(L, light_userdata_value(v));
|
||||
}
|
||||
return pushcount;
|
||||
}
|
||||
data_t data{ {} };
|
||||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||
int pushcount = 0;
|
||||
for (auto&& v : data) {
|
||||
pushcount += push(L, lightuserdata_value(v));
|
||||
}
|
||||
return pushcount;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
||||
const static std::size_t data_t_count = (sizeof(T)+(sizeof(void*)-1)) / sizeof(void*);
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata{ {} };
|
||||
for(std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[i] = get<light_userdata_value>(L, up_value_index(index++));
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
template<typename T>
|
||||
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
||||
const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata{ {} };
|
||||
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[i] = get<lightuserdata_value>(L, up_value_index(index++));
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
||||
template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
#ifndef _MSC_VER
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
#endif // This compiler make me so fucking sad
|
||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
||||
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - meta::count_for_to_pack<I, is_transparent_argument, Args...>::value)...);
|
||||
}
|
||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
||||
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - meta::count_for_to_pack<I, is_transparent_argument, Args...>::value)...);
|
||||
}
|
||||
|
||||
template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
#ifndef _MSC_VER
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||
#endif // This compiler make me so fucking sad
|
||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
||||
fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - meta::count_for_to_pack<I, is_transparent_argument, Args...>::value)...);
|
||||
}
|
||||
} // stack_detail
|
||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
||||
fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I - meta::count_for_to_pack<I, is_transparent_argument, Args...>::value)...);
|
||||
}
|
||||
} // stack_detail
|
||||
|
||||
inline void remove( lua_State* L, int index, int count ) {
|
||||
if ( count < 1 )
|
||||
return;
|
||||
int top = lua_gettop(L);
|
||||
if ( index == -1 || top == index ) {
|
||||
// Slice them right off the top
|
||||
lua_pop( L, static_cast<int>(count) );
|
||||
return;
|
||||
}
|
||||
inline void remove(lua_State* L, int index, int count) {
|
||||
if (count < 1)
|
||||
return;
|
||||
int top = lua_gettop(L);
|
||||
if (index == -1 || top == index) {
|
||||
// Slice them right off the top
|
||||
lua_pop(L, static_cast<int>(count));
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove each item one at a time using stack operations
|
||||
// Probably slower, maybe, haven't benchmarked,
|
||||
// but necessary
|
||||
if ( index < 0 ) {
|
||||
index = lua_gettop(L) + (index + 1);
|
||||
}
|
||||
int last = index + count;
|
||||
for ( int i = index; i < last; ++i ) {
|
||||
lua_remove(L, i);
|
||||
}
|
||||
}
|
||||
// Remove each item one at a time using stack operations
|
||||
// Probably slower, maybe, haven't benchmarked,
|
||||
// but necessary
|
||||
if (index < 0) {
|
||||
index = lua_gettop(L) + (index + 1);
|
||||
}
|
||||
int last = index + count;
|
||||
for (int i = index; i < last; ++i) {
|
||||
lua_remove(L, i);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> args_indices;
|
||||
return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> args_indices;
|
||||
return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> args_indices;
|
||||
stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> args_indices;
|
||||
stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||
lua_pop(L, nargs);
|
||||
return 0;
|
||||
}
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||
lua_pop(L, nargs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>>
|
||||
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||
lua_pop(L, nargs);
|
||||
return push_reference(L, std::forward<decltype(r)>(r));
|
||||
}
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>>
|
||||
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||
lua_pop(L, nargs);
|
||||
return push_reference(L, std::forward<decltype(r)>(r));
|
||||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs>
|
||||
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
return call_into_lua(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
}
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs>
|
||||
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
return call_into_lua(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
}
|
||||
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||
luaL_getmetatable(L, key.c_str());
|
||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||
lua_pop(L, 1);
|
||||
return call_syntax::colon;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return call_syntax::dot;
|
||||
}
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||
luaL_getmetatable(L, key.c_str());
|
||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||
lua_pop(L, 1);
|
||||
return call_syntax::colon;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return call_syntax::dot;
|
||||
}
|
||||
|
||||
inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
|
||||
inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
|
||||
#ifdef SOL_LUAJIT
|
||||
lua_pushlightuserdata(L, (void*)handler);
|
||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
||||
lua_pop(L, 1);
|
||||
lua_pushlightuserdata(L, (void*)handler);
|
||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
||||
lua_pop(L, 1);
|
||||
#else
|
||||
(void)L;
|
||||
(void)handler;
|
||||
(void)L;
|
||||
(void)handler;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void luajit_exception_off(lua_State* L) {
|
||||
inline void luajit_exception_off(lua_State* L) {
|
||||
#ifdef SOL_LUAJIT
|
||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
|
||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
|
||||
#else
|
||||
(void)L;
|
||||
(void)L;
|
||||
#endif
|
||||
}
|
||||
} // stack
|
||||
} // sol
|
||||
}
|
||||
}} // sol::stack
|
||||
|
||||
#endif // SOL_STACK_HPP
|
||||
|
|
|
@ -260,7 +260,7 @@ struct checker<T, type::userdata, C> {
|
|||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
if (meta::any<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||
return true;
|
||||
if (lua_getmetatable(L, index) == 0) {
|
||||
return true;
|
||||
|
@ -271,30 +271,29 @@ struct checker<T, type::userdata, C> {
|
|||
return true;
|
||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
||||
return true;
|
||||
bool success = true;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
bool success = detail::catch_check<T>(basecast);
|
||||
if (stack::get<type>(L) != type::nil) {
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
success = detail::catch_check<T>(basecast);
|
||||
}
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
if (stack::get<type>(L) != type::nil) {
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
success = ic(typeid(T));
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(typeid(T));
|
||||
#else
|
||||
// Topkek
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
if (stack::get<type>(L) != type::nil) {
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
success = ic(detail::id_for<T>::value);
|
||||
}
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
bool success = ic(detail::id_for<T>::value);
|
||||
#endif // No Runtime Type Information || Exceptions
|
||||
lua_pop(L, 2);
|
||||
if (!success) {
|
||||
|
|
|
@ -84,9 +84,9 @@ struct getter<userdata_value> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct getter<light_userdata_value> {
|
||||
static light_userdata_value get(lua_State* L, int index = -1) {
|
||||
return light_userdata_value( lua_touserdata(L, index) );
|
||||
struct getter<lightuserdata_value> {
|
||||
static lightuserdata_value get(lua_State* L, int index = -1) {
|
||||
return lightuserdata_value( lua_touserdata(L, index) );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -262,8 +262,8 @@ struct pusher<void*> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct pusher<light_userdata_value> {
|
||||
static int push(lua_State* L, light_userdata_value userdata) {
|
||||
struct pusher<lightuserdata_value> {
|
||||
static int push(lua_State* L, lightuserdata_value userdata) {
|
||||
lua_pushlightuserdata(L, userdata);
|
||||
return 1;
|
||||
}
|
||||
|
@ -279,21 +279,39 @@ struct pusher<light<T>> {
|
|||
|
||||
template<typename T>
|
||||
struct pusher<user<T>> {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args ) {
|
||||
template <bool with_meta = true, typename... Args>
|
||||
static int push_with(lua_State* L, Args&&... args ) {
|
||||
// A dumb pusher
|
||||
void* rawdata = lua_newuserdata(L, sizeof(T));
|
||||
std::allocator<T> alloc;
|
||||
alloc.construct(static_cast<T*>(rawdata), std::forward<Args>(args)...);
|
||||
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
||||
// Make sure we have a plain GC set for this data
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushlightuserdata(L, rawdata);
|
||||
lua_pushcclosure(L, cdel, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_setmetatable(L, -2);
|
||||
if (with_meta) {
|
||||
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
||||
// Make sure we have a plain GC set for this data
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushlightuserdata(L, rawdata);
|
||||
lua_pushcclosure(L, cdel, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const user<T>& u) {
|
||||
return push_with(L, u.value);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, user<T>&& u) {
|
||||
return push_with(L, std::move(u.value));
|
||||
}
|
||||
|
||||
static int push(lua_State* L, no_metatable_t, const user<T>& u) {
|
||||
return push_with<false>(L, u.value);
|
||||
}
|
||||
|
||||
static int push(lua_State* L, no_metatable_t, user<T>&& u) {
|
||||
return push_with<false>(L, std::move(u.value));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -110,6 +110,9 @@ inline bool operator!=(nil_t, nil_t) { return false; }
|
|||
struct metatable_key_t {};
|
||||
const metatable_key_t metatable_key = {};
|
||||
|
||||
struct no_metatable_t {};
|
||||
const no_metatable_t no_metatable = {};
|
||||
|
||||
typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction;
|
||||
|
||||
template <typename T>
|
||||
|
@ -177,9 +180,9 @@ struct absolute_index {
|
|||
operator int() const { return index; }
|
||||
};
|
||||
|
||||
struct light_userdata_value {
|
||||
struct lightuserdata_value {
|
||||
void* value;
|
||||
light_userdata_value(void* data) : value(data) {}
|
||||
lightuserdata_value(void* data) : value(data) {}
|
||||
operator void*() const { return value; }
|
||||
};
|
||||
|
||||
|
@ -533,7 +536,7 @@ template <typename A, typename B>
|
|||
struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<light_userdata_value> : std::integral_constant<type, type::lightuserdata> {};
|
||||
struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
||||
|
@ -600,12 +603,12 @@ template <typename T>
|
|||
struct lua_type_of : detail::lua_type_of<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct is_lua_primitive : std::integral_constant<bool,
|
||||
type::userdata != lua_type_of<meta::unqualified_t<T>>::value
|
||||
|| std::is_base_of<reference, meta::unqualified_t<T>>::value
|
||||
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value
|
||||
|| meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value
|
||||
|| meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value
|
||||
struct is_lua_primitive : std::integral_constant<bool,
|
||||
type::userdata != lua_type_of<meta::unqualified_t<T>>::value
|
||||
|| std::is_base_of<reference, meta::unqualified_t<T>>::value
|
||||
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value
|
||||
|| meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value
|
||||
|| meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value
|
||||
> { };
|
||||
|
||||
template <typename T>
|
||||
|
@ -617,7 +620,7 @@ struct is_lua_primitive<T*> : std::true_type {};
|
|||
template <>
|
||||
struct is_lua_primitive<userdata_value> : std::true_type {};
|
||||
template <>
|
||||
struct is_lua_primitive<light_userdata_value> : std::true_type {};
|
||||
struct is_lua_primitive<lightuserdata_value> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> {};
|
||||
|
||||
|
|
|
@ -125,23 +125,6 @@ namespace sol {
|
|||
l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc };
|
||||
++index;
|
||||
}
|
||||
if (baseclasscast != nullptr)
|
||||
return index;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = baseclasscast = (void*)&detail::throw_as<T>;
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T>::type_cast;
|
||||
#else
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T>::type_cast;
|
||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -172,6 +155,7 @@ namespace sol {
|
|||
baseclasscheck = (void*)&detail::inheritance<T, Args...>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Args...>::type_cast;
|
||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||
return endindex;
|
||||
}
|
||||
|
||||
template <std::size_t I = 0, typename N, typename F, typename... Args, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>>
|
||||
|
@ -249,6 +233,10 @@ namespace sol {
|
|||
virtual int push_um(lua_State* L) override {
|
||||
return stack::push(L, std::move(*this));
|
||||
}
|
||||
|
||||
~usertype_metatable() override {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
|
@ -258,15 +246,22 @@ namespace sol {
|
|||
typedef usertype_metatable<T, Tuple> umt_t;
|
||||
typedef typename umt_t::regs_t regs_t;
|
||||
|
||||
template <std::size_t... I>
|
||||
static int push(std::index_sequence<I...>, lua_State* L, usertype_metatable<T, Tuple>&& umx) {
|
||||
static usertype_metatable<T, Tuple>& make_cleanup(lua_State* L, usertype_metatable<T, Tuple>&& umx) {
|
||||
// Make sure userdata's memory is properly in lua first,
|
||||
// otherwise all the light userdata we make later will become invalid
|
||||
stack::push(L, make_user(std::move(umx)));
|
||||
usertype_metatable<T, Tuple>& um = stack::get<light<usertype_metatable<T, Tuple>>>(L, -1);
|
||||
reference umt(L, -1);
|
||||
umt.pop();
|
||||
|
||||
// Create the top level thing that will act as our deleter later on
|
||||
const char* gcmetakey = &usertype_traits<T>::gc_table[0];
|
||||
stack::set_field<true>(L, gcmetakey, make_user(std::move(umx)));
|
||||
stack::get_field<true>(L, gcmetakey);
|
||||
return stack::pop<light<usertype_metatable<T, Tuple>>>(L);
|
||||
}
|
||||
|
||||
template <std::size_t... I>
|
||||
static int push(std::index_sequence<I...>, lua_State* L, usertype_metatable<T, Tuple>&& umx) {
|
||||
|
||||
usertype_metatable<T, Tuple>& um = make_cleanup(L, std::move(umx));
|
||||
|
||||
// Now use um
|
||||
const bool& mustindex = um.mustindex;
|
||||
stack_reference t;
|
||||
|
@ -328,27 +323,6 @@ namespace sol {
|
|||
if (i < 2) {
|
||||
t.pop();
|
||||
}
|
||||
else {
|
||||
// NOT NEEDED
|
||||
// Perhaps we should look into
|
||||
// whether or not doing ti like this
|
||||
// is better than just letting user<T> handle it?
|
||||
|
||||
// Add cleanup to metatable
|
||||
// Essentially, when the metatable dies,
|
||||
// this too will call the class and kill itself
|
||||
/*const char* metakey = &usertype_traits<T>::gc_table[0];
|
||||
lua_createtable(L, 1, 0);
|
||||
stack_reference cleanup(L, -1);
|
||||
stack::set_field(L, meta_function::garbage_collect, make_closure(umt_t::gc_call, umt), cleanup.stack_index());
|
||||
stack::set_field(L, metatable_key, cleanup, cleanup.stack_index());
|
||||
// Needs to be raw since we
|
||||
// override the metatable's metatable on 't'
|
||||
// otherwise, it will trigger the __index metamethod
|
||||
// we just set
|
||||
stack::raw_set_field(L, metakey, t, t.stack_index());
|
||||
cleanup.pop();*/
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue
Block a user