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:
|
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**
|
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:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:linenos:
|
: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>
|
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||||
struct agnostic_lua_call_wrapper {
|
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 wrapper<meta::unqualified_t<F>> wrap;
|
||||||
typedef typename wrap::returns_list returns_list;
|
typedef typename wrap::returns_list returns_list;
|
||||||
typedef typename wrap::free_args_list args_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);
|
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 wrapper<meta::unqualified_t<F>> wrap;
|
||||||
typedef typename wrap::free_args_list args_list;
|
typedef typename wrap::free_args_list args_list;
|
||||||
typedef typename wrap::returns_list returns_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);
|
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);
|
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F, bool is_index, bool is_variable>
|
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>> {
|
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 wrapper<meta::unqualified_t<F>> wrap;
|
||||||
typedef typename wrap::returns_list returns_list;
|
typedef typename wrap::returns_list returns_list;
|
||||||
typedef typename wrap::args_list args_list;
|
typedef typename wrap::args_list args_list;
|
||||||
|
@ -204,7 +204,7 @@ namespace call_detail {
|
||||||
|
|
||||||
template <bool is_index, bool is_variable, typename C>
|
template <bool is_index, bool is_variable, typename C>
|
||||||
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, 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");
|
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>> {
|
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;
|
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 wrapper<meta::unqualified_t<F>> wrap;
|
||||||
typedef typename wrap::args_list args_list;
|
typedef typename wrap::args_list args_list;
|
||||||
typedef typename wrap::object_type object_type;
|
typedef typename wrap::object_type object_type;
|
||||||
|
@ -233,20 +233,20 @@ namespace call_detail {
|
||||||
#endif // Safety
|
#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");
|
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;
|
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);
|
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");
|
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);
|
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>> {
|
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;
|
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 wrapper<meta::unqualified_t<F>> wrap;
|
||||||
typedef typename wrap::object_type object_type;
|
typedef typename wrap::object_type object_type;
|
||||||
typedef typename wrap::returns_list returns_list;
|
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;
|
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);
|
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));
|
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;
|
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);
|
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));
|
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>
|
template <std::size_t limit>
|
||||||
static void func_gc(std::false_type, lua_State* L) {
|
static void func_gc(std::false_type, lua_State* L) {
|
||||||
for (std::size_t i = 0; i < limit; ++i) {
|
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)
|
if (value == nullptr)
|
||||||
continue;
|
continue;
|
||||||
base_function* obj = static_cast<base_function*>(value);
|
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) {
|
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);
|
void** pinheritancedata = static_cast<void**>(ludata);
|
||||||
return base_call(L, *pinheritancedata);
|
return base_call(L, *pinheritancedata);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ inline int gc(lua_State* L) {
|
||||||
template<std::size_t I>
|
template<std::size_t I>
|
||||||
inline int usertype_call(lua_State* L) {
|
inline int usertype_call(lua_State* L) {
|
||||||
// Zero-based template parameter, but upvalues start at 1
|
// 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>
|
template<std::size_t I>
|
||||||
|
|
272
sol/stack.hpp
272
sol/stack.hpp
|
@ -34,171 +34,169 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol { namespace stack {
|
||||||
namespace stack {
|
namespace stack_detail {
|
||||||
namespace stack_detail {
|
template <typename T>
|
||||||
template <typename T>
|
struct is_this_state_raw : std::false_type {};
|
||||||
struct is_this_state_raw : std::false_type {};
|
template <>
|
||||||
template <>
|
struct is_this_state_raw<this_state> : std::true_type {};
|
||||||
struct is_this_state_raw<this_state> : std::true_type {};
|
template <typename T>
|
||||||
template <typename T>
|
using is_this_state = is_this_state_raw<meta::unqualified_t<T>>;
|
||||||
using is_this_state = is_this_state_raw<meta::unqualified_t<T>>;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline int push_as_upvalues(lua_State* L, T& item) {
|
inline int push_as_upvalues(lua_State* L, T& item) {
|
||||||
typedef std::decay_t<T> TValue;
|
typedef std::decay_t<T> TValue;
|
||||||
const static std::size_t itemsize = sizeof(TValue);
|
const static std::size_t itemsize = sizeof(TValue);
|
||||||
const static std::size_t voidsize = sizeof(void*);
|
const static std::size_t voidsize = sizeof(void*);
|
||||||
const static std::size_t voidsizem1 = voidsize - 1;
|
const static std::size_t voidsizem1 = voidsize - 1;
|
||||||
const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
|
const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
|
||||||
typedef std::array<void*, data_t_count> data_t;
|
typedef std::array<void*, data_t_count> data_t;
|
||||||
|
|
||||||
data_t data{{}};
|
data_t data{ {} };
|
||||||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||||
int pushcount = 0;
|
int pushcount = 0;
|
||||||
for(auto&& v : data) {
|
for (auto&& v : data) {
|
||||||
pushcount += push(L, light_userdata_value(v));
|
pushcount += push(L, lightuserdata_value(v));
|
||||||
}
|
}
|
||||||
return pushcount;
|
return pushcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
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*);
|
const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
|
||||||
typedef std::array<void*, data_t_count> data_t;
|
typedef std::array<void*, data_t_count> data_t;
|
||||||
data_t voiddata{ {} };
|
data_t voiddata{ {} };
|
||||||
for(std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
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++));
|
voiddata[i] = get<lightuserdata_value>(L, up_value_index(index++));
|
||||||
}
|
}
|
||||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), 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>>
|
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) {
|
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
|
#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
|
#endif // This compiler make me so fucking sad
|
||||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
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)...);
|
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>
|
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) {
|
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
|
#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
|
#endif // This compiler make me so fucking sad
|
||||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
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)...);
|
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
|
} // stack_detail
|
||||||
|
|
||||||
inline void remove( lua_State* L, int index, int count ) {
|
inline void remove(lua_State* L, int index, int count) {
|
||||||
if ( count < 1 )
|
if (count < 1)
|
||||||
return;
|
return;
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
if ( index == -1 || top == index ) {
|
if (index == -1 || top == index) {
|
||||||
// Slice them right off the top
|
// Slice them right off the top
|
||||||
lua_pop( L, static_cast<int>(count) );
|
lua_pop(L, static_cast<int>(count));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove each item one at a time using stack operations
|
// Remove each item one at a time using stack operations
|
||||||
// Probably slower, maybe, haven't benchmarked,
|
// Probably slower, maybe, haven't benchmarked,
|
||||||
// but necessary
|
// but necessary
|
||||||
if ( index < 0 ) {
|
if (index < 0) {
|
||||||
index = lua_gettop(L) + (index + 1);
|
index = lua_gettop(L) + (index + 1);
|
||||||
}
|
}
|
||||||
int last = index + count;
|
int last = index + count;
|
||||||
for ( int i = index; i < last; ++i ) {
|
for (int i = index; i < last; ++i) {
|
||||||
lua_remove(L, 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>>
|
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) {
|
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;
|
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)...);
|
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>>
|
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) {
|
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)...);
|
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>
|
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) {
|
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;
|
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)...);
|
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>
|
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) {
|
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)...);
|
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>>
|
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) {
|
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)...);
|
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>
|
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) {
|
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)...);
|
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>
|
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) {
|
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)...);
|
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;
|
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return 0;
|
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>>
|
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) {
|
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)...);
|
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;
|
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop - meta::count_for_pack<stack_detail::is_this_state, Args...>::value;
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return push_reference(L, std::forward<decltype(r)>(r));
|
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>
|
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) {
|
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||||
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
||||||
typedef typename traits_type::args_list args_list;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef typename traits_type::returns_list returns_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)...);
|
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) {
|
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||||
luaL_getmetatable(L, key.c_str());
|
luaL_getmetatable(L, key.c_str());
|
||||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return call_syntax::colon;
|
return call_syntax::colon;
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return call_syntax::dot;
|
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
|
#ifdef SOL_LUAJIT
|
||||||
lua_pushlightuserdata(L, (void*)handler);
|
lua_pushlightuserdata(L, (void*)handler);
|
||||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
#else
|
#else
|
||||||
(void)L;
|
(void)L;
|
||||||
(void)handler;
|
(void)handler;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void luajit_exception_off(lua_State* L) {
|
inline void luajit_exception_off(lua_State* L) {
|
||||||
#ifdef SOL_LUAJIT
|
#ifdef SOL_LUAJIT
|
||||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
|
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
|
||||||
#else
|
#else
|
||||||
(void)L;
|
(void)L;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} // stack
|
}} // sol::stack
|
||||||
} // sol
|
|
||||||
|
|
||||||
#endif // SOL_STACK_HPP
|
#endif // SOL_STACK_HPP
|
||||||
|
|
|
@ -260,7 +260,7 @@ struct checker<T, type::userdata, C> {
|
||||||
handler(L, index, type::userdata, indextype);
|
handler(L, index, type::userdata, indextype);
|
||||||
return false;
|
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;
|
return true;
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -271,30 +271,29 @@ struct checker<T, type::userdata, C> {
|
||||||
return true;
|
return true;
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
||||||
return true;
|
return true;
|
||||||
|
bool success = true;
|
||||||
#ifndef SOL_NO_EXCEPTIONS
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
void* basecastdata = lua_touserdata(L, -1);
|
if (stack::get<type>(L) != type::nil) {
|
||||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
bool success = detail::catch_check<T>(basecast);
|
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||||
|
success = detail::catch_check<T>(basecast);
|
||||||
|
}
|
||||||
#elif !defined(SOL_NO_RTTI)
|
#elif !defined(SOL_NO_RTTI)
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
if (stack::get<type>(L) == type::nil) {
|
if (stack::get<type>(L) != type::nil) {
|
||||||
lua_pop(L, 2);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
return false;
|
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
|
#else
|
||||||
// Topkek
|
// Topkek
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
if (stack::get<type>(L) == type::nil) {
|
if (stack::get<type>(L) != type::nil) {
|
||||||
lua_pop(L, 2);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
return false;
|
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
|
#endif // No Runtime Type Information || Exceptions
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
|
@ -84,9 +84,9 @@ struct getter<userdata_value> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<light_userdata_value> {
|
struct getter<lightuserdata_value> {
|
||||||
static light_userdata_value get(lua_State* L, int index = -1) {
|
static lightuserdata_value get(lua_State* L, int index = -1) {
|
||||||
return light_userdata_value( lua_touserdata(L, index) );
|
return lightuserdata_value( lua_touserdata(L, index) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -262,8 +262,8 @@ struct pusher<void*> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct pusher<light_userdata_value> {
|
struct pusher<lightuserdata_value> {
|
||||||
static int push(lua_State* L, light_userdata_value userdata) {
|
static int push(lua_State* L, lightuserdata_value userdata) {
|
||||||
lua_pushlightuserdata(L, userdata);
|
lua_pushlightuserdata(L, userdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -279,21 +279,39 @@ struct pusher<light<T>> {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<user<T>> {
|
struct pusher<user<T>> {
|
||||||
template <typename... Args>
|
template <bool with_meta = true, typename... Args>
|
||||||
static int push(lua_State* L, Args&&... args ) {
|
static int push_with(lua_State* L, Args&&... args ) {
|
||||||
// A dumb pusher
|
// A dumb pusher
|
||||||
void* rawdata = lua_newuserdata(L, sizeof(T));
|
void* rawdata = lua_newuserdata(L, sizeof(T));
|
||||||
std::allocator<T> alloc;
|
std::allocator<T> alloc;
|
||||||
alloc.construct(static_cast<T*>(rawdata), std::forward<Args>(args)...);
|
alloc.construct(static_cast<T*>(rawdata), std::forward<Args>(args)...);
|
||||||
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
if (with_meta) {
|
||||||
// Make sure we have a plain GC set for this data
|
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
||||||
lua_createtable(L, 0, 1);
|
// Make sure we have a plain GC set for this data
|
||||||
lua_pushlightuserdata(L, rawdata);
|
lua_createtable(L, 0, 1);
|
||||||
lua_pushcclosure(L, cdel, 1);
|
lua_pushlightuserdata(L, rawdata);
|
||||||
lua_setfield(L, -2, "__gc");
|
lua_pushcclosure(L, cdel, 1);
|
||||||
lua_setmetatable(L, -2);
|
lua_setfield(L, -2, "__gc");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
}
|
||||||
return 1;
|
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<>
|
template<>
|
||||||
|
|
|
@ -110,6 +110,9 @@ inline bool operator!=(nil_t, nil_t) { return false; }
|
||||||
struct metatable_key_t {};
|
struct metatable_key_t {};
|
||||||
const metatable_key_t metatable_key = {};
|
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;
|
typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -177,9 +180,9 @@ struct absolute_index {
|
||||||
operator int() const { return index; }
|
operator int() const { return index; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct light_userdata_value {
|
struct lightuserdata_value {
|
||||||
void* value;
|
void* value;
|
||||||
light_userdata_value(void* data) : value(data) {}
|
lightuserdata_value(void* data) : value(data) {}
|
||||||
operator void*() const { return value; }
|
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> {};
|
struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> {};
|
||||||
|
|
||||||
template <>
|
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 <>
|
template <>
|
||||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
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> {};
|
struct lua_type_of : detail::lua_type_of<T> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_primitive : std::integral_constant<bool,
|
struct is_lua_primitive : std::integral_constant<bool,
|
||||||
type::userdata != lua_type_of<meta::unqualified_t<T>>::value
|
type::userdata != lua_type_of<meta::unqualified_t<T>>::value
|
||||||
|| std::is_base_of<reference, 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
|
|| 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::tuple, meta::unqualified_t<T>>::value
|
||||||
|| meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value
|
|| meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value
|
||||||
> { };
|
> { };
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -617,7 +620,7 @@ struct is_lua_primitive<T*> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_lua_primitive<userdata_value> : std::true_type {};
|
struct is_lua_primitive<userdata_value> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_lua_primitive<light_userdata_value> : std::true_type {};
|
struct is_lua_primitive<lightuserdata_value> : std::true_type {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_primitive<non_null<T>> : is_lua_primitive<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 };
|
l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc };
|
||||||
++index;
|
++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;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +155,7 @@ namespace sol {
|
||||||
baseclasscheck = (void*)&detail::inheritance<T, Args...>::type_check;
|
baseclasscheck = (void*)&detail::inheritance<T, Args...>::type_check;
|
||||||
baseclasscast = (void*)&detail::inheritance<T, Args...>::type_cast;
|
baseclasscast = (void*)&detail::inheritance<T, Args...>::type_cast;
|
||||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
#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>>
|
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 {
|
virtual int push_um(lua_State* L) override {
|
||||||
return stack::push(L, std::move(*this));
|
return stack::push(L, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~usertype_metatable() override {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace stack {
|
namespace stack {
|
||||||
|
@ -258,15 +246,22 @@ namespace sol {
|
||||||
typedef usertype_metatable<T, Tuple> umt_t;
|
typedef usertype_metatable<T, Tuple> umt_t;
|
||||||
typedef typename umt_t::regs_t regs_t;
|
typedef typename umt_t::regs_t regs_t;
|
||||||
|
|
||||||
template <std::size_t... I>
|
static usertype_metatable<T, Tuple>& make_cleanup(lua_State* L, usertype_metatable<T, Tuple>&& umx) {
|
||||||
static int push(std::index_sequence<I...>, lua_State* L, usertype_metatable<T, Tuple>&& umx) {
|
|
||||||
// Make sure userdata's memory is properly in lua first,
|
// Make sure userdata's memory is properly in lua first,
|
||||||
// otherwise all the light userdata we make later will become invalid
|
// 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
|
// Now use um
|
||||||
const bool& mustindex = um.mustindex;
|
const bool& mustindex = um.mustindex;
|
||||||
stack_reference t;
|
stack_reference t;
|
||||||
|
@ -328,27 +323,6 @@ namespace sol {
|
||||||
if (i < 2) {
|
if (i < 2) {
|
||||||
t.pop();
|
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;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user