Preserve internal type of member function calls / pointers, even if they're base types linked to derived types

This commit is contained in:
ThePhD 2016-06-22 13:26:27 -04:00
parent 0fef6556e4
commit 97c132d91d
3 changed files with 65 additions and 59 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);
} }