mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Preserve internal type of member function calls / pointers, even if they're base types linked to derived types
This commit is contained in:
parent
0fef6556e4
commit
97c132d91d
96
sol/call.hpp
96
sol/call.hpp
|
@ -166,28 +166,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
|
||||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
|
||||||
typedef typename wrap::returns_list returns_list;
|
|
||||||
typedef typename wrap::args_list args_list;
|
|
||||||
typedef typename wrap::caller caller;
|
|
||||||
typedef typename wrap::object_type object_type;
|
|
||||||
|
|
||||||
#ifdef SOL_SAFE_USERTYPE
|
|
||||||
object_type* o = stack::get<object_type*>(L, 1);
|
|
||||||
if (o == nullptr) {
|
|
||||||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
|
||||||
}
|
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
|
||||||
#else
|
|
||||||
object_type& o = stack::get<object_type&>(L, 1);
|
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
|
||||||
#endif // Safety
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool is_index, bool is_variable, typename C>
|
template <bool is_index, bool is_variable, typename C>
|
||||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, C> {
|
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, C> {
|
||||||
static int call(lua_State* L, lua_r_CFunction f) {
|
static int call(lua_State* L, lua_r_CFunction f) {
|
||||||
|
@ -209,8 +187,48 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F, bool is_variable>
|
template <bool is_index, bool is_variable, typename C>
|
||||||
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<no_construction, is_index, is_variable, C> {
|
||||||
|
static int call(lua_State* L, no_construction&) {
|
||||||
|
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Args, bool is_index, bool is_variable, typename C>
|
||||||
|
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, C> {
|
||||||
|
static int call(lua_State*, bases<Args...>&) {
|
||||||
|
// Uh. How did you even call this, lul
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
||||||
|
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
||||||
|
|
||||||
|
template <typename T, typename F, bool is_index, bool is_variable>
|
||||||
|
struct lua_call_wrapper<T, F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||||
|
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;
|
||||||
|
typedef typename wrap::caller caller;
|
||||||
|
typedef typename wrap::object_type object_type;
|
||||||
|
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
object_type* o = static_cast<object_type*>(stack::get<T*>(L, 1));
|
||||||
|
if (o == nullptr) {
|
||||||
|
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
||||||
|
}
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||||
|
#else
|
||||||
|
object_type& o = static_cast<object_type&>(stack::get<T&>(L, 1));
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||||
|
#endif // Safety
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename F, bool is_variable>
|
||||||
|
struct lua_call_wrapper<T, 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) {
|
||||||
|
@ -219,7 +237,7 @@ namespace sol {
|
||||||
typedef typename wrap::object_type object_type;
|
typedef typename wrap::object_type object_type;
|
||||||
typedef typename wrap::caller caller;
|
typedef typename wrap::caller caller;
|
||||||
#ifdef SOL_SAFE_USERTYPE
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
object_type* o = stack::get<object_type*>(L, 1);
|
object_type* o = static_cast<object_type*>(stack::get<T*>(L, 1));
|
||||||
if (o == nullptr) {
|
if (o == nullptr) {
|
||||||
if (is_variable) {
|
if (is_variable) {
|
||||||
return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
|
return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)");
|
||||||
|
@ -228,7 +246,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||||
#else
|
#else
|
||||||
object_type& o = stack::get<object_type&>(L, 1);
|
object_type& o = static_cast<object_type&>(stack::get<T&>(L, 1));
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
|
@ -251,8 +269,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F, bool is_variable>
|
template <typename T, typename F, bool is_variable>
|
||||||
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
struct lua_call_wrapper<T, 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) {
|
||||||
|
@ -261,7 +279,7 @@ namespace sol {
|
||||||
typedef typename wrap::returns_list returns_list;
|
typedef typename wrap::returns_list returns_list;
|
||||||
typedef typename wrap::caller caller;
|
typedef typename wrap::caller caller;
|
||||||
#ifdef SOL_SAFE_USERTYPE
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
object_type* o = stack::get<object_type*>(L, 1);
|
object_type* o = static_cast<object_type*>(stack::get<T*>(L, 1));
|
||||||
if (o == nullptr) {
|
if (o == nullptr) {
|
||||||
if (is_variable) {
|
if (is_variable) {
|
||||||
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
|
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
|
||||||
|
@ -270,30 +288,12 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
|
||||||
#else
|
#else
|
||||||
object_type& o = stack::get<object_type&>(L, 1);
|
object_type& o = static_cast<object_type&>(stack::get<T&>(L, 1));
|
||||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool is_index, bool is_variable, typename C>
|
|
||||||
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, C> {
|
|
||||||
static int call(lua_State* L, no_construction&) {
|
|
||||||
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args, bool is_index, bool is_variable, typename C>
|
|
||||||
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, C> {
|
|
||||||
static int call(lua_State*, bases<Args...>&) {
|
|
||||||
// Uh. How did you even call this, lul
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
|
||||||
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
|
||||||
|
|
||||||
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
||||||
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
||||||
typedef sol::constructor_list<Args...> F;
|
typedef sol::constructor_list<Args...> F;
|
||||||
|
|
|
@ -179,6 +179,18 @@ namespace sol {
|
||||||
return call_syntax::dot;
|
return call_syntax::dot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void script(lua_State* L, const std::string& code) {
|
||||||
|
if (luaL_dostring(L, code.c_str())) {
|
||||||
|
lua_error(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void script_file(lua_State* L, const std::string& filename) {
|
||||||
|
if (luaL_dofile(L, filename.c_str())) {
|
||||||
|
lua_error(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -208,29 +208,23 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
object require_script(const std::string& key, const std::string& code, bool create_global = true) {
|
object require_script(const std::string& key, const std::string& code, bool create_global = true) {
|
||||||
return require_core(key, [this, &code]() {this->script(code); }, create_global);
|
return require_core(key, [this, &code]() {stack::script(L, code); }, create_global);
|
||||||
}
|
}
|
||||||
|
|
||||||
object require_file(const std::string& key, const std::string& file, bool create_global = true) {
|
object require_file(const std::string& key, const std::string& filename, bool create_global = true) {
|
||||||
return require_core(key, [this, &file]() {this->script_file(file); }, create_global);
|
return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result script(const std::string& code) {
|
function_result script(const std::string& code) {
|
||||||
int index = (::std::max)(lua_gettop(L), 1);
|
int index = (::std::max)(lua_gettop(L), 1);
|
||||||
if (luaL_dostring(L, code.c_str())) {
|
stack::script(L, code);
|
||||||
lua_error(L);
|
|
||||||
// Rest of code will never be run because lua_error jumps out
|
|
||||||
}
|
|
||||||
int returns = lua_gettop(L) - (index - 1);
|
int returns = lua_gettop(L) - (index - 1);
|
||||||
return function_result(L, index, returns);
|
return function_result(L, index, returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result script_file(const std::string& filename) {
|
function_result script_file(const std::string& filename) {
|
||||||
int index = (::std::max)(lua_gettop(L), 1);
|
int index = (::std::max)(lua_gettop(L), 1);
|
||||||
if (luaL_dofile(L, filename.c_str())) {
|
stack::script_file(L, filename);
|
||||||
lua_error(L);
|
|
||||||
// Rest of code will never be run because lua_error jumps out
|
|
||||||
}
|
|
||||||
int returns = lua_gettop(L) - index;
|
int returns = lua_gettop(L) - index;
|
||||||
return function_result(L, index, returns);
|
return function_result(L, index, returns);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user