mirror of
https://github.com/edubart/otclient.git
synced 2026-01-16 18:41:30 +01:00
Lua binder compability changes
* A lot of changes in lua binder to compile with clang's libc++ * Add more portability to luabinder * Remove const keyword from bound lua functions * Deprecate std::bind usage with luabinder replace its usage with registerSingletonClass/bindSingletonFunction for binding singleton classes * Fix a bug in lua binder where calling functions with bil object would make the client crash * More fixes to compile with clang
This commit is contained in:
@@ -55,7 +55,7 @@ namespace luabinder
|
||||
template<>
|
||||
struct pack_values_into_tuple<0> {
|
||||
template<typename Tuple>
|
||||
static void call(Tuple &tuple, LuaInterface* lua) { }
|
||||
static void call(Tuple& tuple, LuaInterface* lua) { }
|
||||
};
|
||||
|
||||
/// C++ function caller that can push results to lua
|
||||
@@ -135,7 +135,7 @@ namespace luabinder
|
||||
};
|
||||
|
||||
template<typename Lambda>
|
||||
typename std::enable_if<std::is_class<Lambda>::value, LuaCppFunction>::type bind_fun(const Lambda& f) {
|
||||
typename std::enable_if<std::is_constructible<decltype(&Lambda::operator())>::value, LuaCppFunction>::type bind_fun(const Lambda& f) {
|
||||
typedef decltype(&Lambda::operator()) F;
|
||||
return bind_lambda_fun<F>::call(f);
|
||||
}
|
||||
@@ -146,102 +146,58 @@ namespace luabinder
|
||||
return bind_fun(std::function<Ret(Args...)>(f));
|
||||
}
|
||||
|
||||
// a tuple_element that works with the next algorithm
|
||||
template<std::size_t __i, typename _Tp>
|
||||
struct tuple_element;
|
||||
template<std::size_t __i, typename _Head, typename... _Tail>
|
||||
struct tuple_element<__i, std::tuple<_Head, _Tail...> >
|
||||
: tuple_element<__i - 1, std::tuple<_Tail...> > { };
|
||||
template<typename _Head, typename... _Tail>
|
||||
struct tuple_element<0, std::tuple<_Head, _Tail...> > { typedef _Head type; };
|
||||
template<typename _Head>
|
||||
struct tuple_element<-1,std::tuple<_Head>> { typedef void type; };
|
||||
template<std::size_t __i>
|
||||
struct tuple_element<__i,std::tuple<>> { typedef void type; };
|
||||
|
||||
template<typename Enable, int N, typename ArgsTuple, typename HoldersTuple, typename... Args>
|
||||
struct get_holded_tuple;
|
||||
|
||||
// some dirty stuff to extract arguments from std::bind holders
|
||||
template<int N, typename ArgsTuple, typename HoldersTuple, typename... Args>
|
||||
struct get_holded_tuple<
|
||||
typename std::enable_if<
|
||||
(N > 0 && std::is_placeholder<
|
||||
typename tuple_element<N-1, HoldersTuple>::type
|
||||
>::value > 0), void
|
||||
>::type, N, ArgsTuple, HoldersTuple, Args...> {
|
||||
typedef typename std::tuple_element<N-1, HoldersTuple>::type holder_type;
|
||||
typedef typename tuple_element<std::is_placeholder<holder_type>::value-1, ArgsTuple>::type _arg_type;
|
||||
typedef typename remove_const_ref<_arg_type>::type arg_type;
|
||||
typedef typename get_holded_tuple<void, N-1, ArgsTuple, HoldersTuple, arg_type, Args...>::type type;
|
||||
};
|
||||
template<int N, typename ArgsTuple, typename HoldersTuple, typename... Args>
|
||||
struct get_holded_tuple<typename std::enable_if<(N > 0 && std::is_placeholder<typename tuple_element<N-1, HoldersTuple>::type>::value == 0), void>::type, N, ArgsTuple, HoldersTuple, Args...> {
|
||||
typedef typename get_holded_tuple<void, N-1, ArgsTuple, HoldersTuple, Args...>::type type;
|
||||
};
|
||||
template<typename ArgsTuple, typename HoldersTuple, typename... Args>
|
||||
struct get_holded_tuple<void, 0, ArgsTuple, HoldersTuple, Args...> {
|
||||
typedef typename std::tuple<Args...> type;
|
||||
};
|
||||
|
||||
/// Rebind functions already bound by std::bind handling it's placeholders
|
||||
template<typename Ret, typename... Args, typename... Holders>
|
||||
LuaCppFunction bind_fun(const std::_Bind<Ret (*(Holders...))(Args...)>& f) {
|
||||
typedef typename std::tuple<Args...> ArgsTuple;
|
||||
typedef typename std::tuple<Holders...> HoldersTuple;
|
||||
typedef typename get_holded_tuple<void, sizeof...(Holders), ArgsTuple, HoldersTuple>::type Tuple;
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
decltype(f),
|
||||
Tuple>(f);
|
||||
/// Create member function lambdas
|
||||
template<typename Ret, typename C, typename... Args>
|
||||
std::function<Ret(const std::shared_ptr<C>&, const Args&...)> make_mem_func(Ret (C::* f)(Args...)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](const std::shared_ptr<C>& obj, const Args&... args) mutable -> Ret {
|
||||
if(!obj)
|
||||
throw LuaException("failed to call a member function because the passed object is nil");
|
||||
return mf(obj.get(), args...);
|
||||
};
|
||||
}
|
||||
template<typename C, typename... Args>
|
||||
std::function<void(const std::shared_ptr<C>&, const Args&...)> make_mem_func(void (C::* f)(Args...)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](const std::shared_ptr<C>& obj, const Args&... args) mutable -> void {
|
||||
if(!obj)
|
||||
throw LuaException("failed to call a member function because the passed object is nil");
|
||||
mf(obj.get(), args...);
|
||||
};
|
||||
}
|
||||
|
||||
/// Rebind member functions already bound by std::bind handling it's placeholders
|
||||
template<typename Obj, typename Ret, typename... Args, typename... Holders>
|
||||
LuaCppFunction bind_fun(const std::_Bind<std::_Mem_fn<Ret (Obj::*)(Args...)>(Obj*, Holders...)>& f) {
|
||||
typedef typename std::tuple<Args...> ArgsTuple;
|
||||
typedef typename std::tuple<Holders...> HoldersTuple;
|
||||
typedef typename get_holded_tuple<void, sizeof...(Holders), ArgsTuple, HoldersTuple>::type Tuple;
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
decltype(f),
|
||||
Tuple>(f);
|
||||
/// Create member function lambdas for singleton classes
|
||||
template<typename Ret, typename C, typename... Args>
|
||||
std::function<Ret(const Args&...)> make_mem_func_singleton(Ret (C::* f)(Args...), C* instance) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](Args... args) mutable -> Ret { return mf(instance, args...); };
|
||||
}
|
||||
template<typename C, typename... Args>
|
||||
std::function<void(const Args&...)> make_mem_func_singleton(void (C::* f)(Args...), C* instance) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](Args... args) mutable -> void { mf(instance, args...); };
|
||||
}
|
||||
|
||||
template<typename Obj, typename Ret, typename... Args, typename... Holders>
|
||||
LuaCppFunction bind_fun(const std::_Bind<std::_Mem_fn<Ret (Obj::*)(Args...) const>(Obj*, Holders...)>& f) {
|
||||
typedef typename std::tuple<Args...> ArgsTuple;
|
||||
typedef typename std::tuple<Holders...> HoldersTuple;
|
||||
typedef typename get_holded_tuple<void, sizeof...(Holders), ArgsTuple, HoldersTuple>::type Tuple;
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
decltype(f),
|
||||
Tuple>(f);
|
||||
}
|
||||
|
||||
/// Bind customized functions already bound by std::bind
|
||||
template<typename Obj>
|
||||
LuaCppFunction bind_fun(const std::_Bind<std::_Mem_fn<int (Obj::*)(LuaInterface*)>(Obj*, std::_Placeholder<1>)>& f) {
|
||||
return f;
|
||||
}
|
||||
inline
|
||||
LuaCppFunction bind_fun(const std::_Bind<int (*(std::_Placeholder<1>))(LuaInterface*)>& f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
/// Bind member functions
|
||||
template<typename C, typename Ret, class FC, typename... Args>
|
||||
LuaCppFunction bind_mem_fun(Ret (FC::*f)(Args...)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
typedef typename std::tuple<std::shared_ptr<C>, typename remove_const_ref<Args>::type...> Tuple;
|
||||
LuaCppFunction bind_mem_fun(Ret (FC::* f)(Args...)) {
|
||||
typedef typename std::tuple<std::shared_ptr<FC>, typename remove_const_ref<Args>::type...> Tuple;
|
||||
auto lambda = make_mem_func<Ret,FC>(f);
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
decltype(mf),
|
||||
Tuple>(mf);
|
||||
decltype(lambda),
|
||||
Tuple>(lambda);
|
||||
}
|
||||
|
||||
/// Bind singleton member functions
|
||||
template<typename C, typename Ret, class FC, typename... Args>
|
||||
LuaCppFunction bind_mem_fun(Ret (FC::*f)(Args...) const) {
|
||||
auto mf = std::mem_fn(f);
|
||||
typedef typename std::tuple<std::shared_ptr<C>, typename remove_const_ref<Args>::type...> Tuple;
|
||||
LuaCppFunction bind_singleton_mem_fun(Ret (FC::*f)(Args...), C *instance) {
|
||||
typedef typename std::tuple<typename remove_const_ref<Args>::type...> Tuple;
|
||||
assert(instance);
|
||||
auto lambda = make_mem_func_singleton<Ret,FC>(f, static_cast<FC*>(instance));
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
decltype(mf),
|
||||
Tuple>(mf);
|
||||
decltype(lambda),
|
||||
Tuple>(lambda);
|
||||
}
|
||||
|
||||
/// Bind customized member functions
|
||||
|
||||
@@ -66,7 +66,7 @@ void LuaInterface::terminate()
|
||||
closeLuaState();
|
||||
}
|
||||
|
||||
void LuaInterface::registerStaticClass(const std::string& className)
|
||||
void LuaInterface::registerSingletonClass(const std::string& className)
|
||||
{
|
||||
newTable();
|
||||
pushValue();
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
void registerFunctions();
|
||||
|
||||
// functions that will register all script stuff in lua global environment
|
||||
void registerStaticClass(const std::string& className);
|
||||
void registerSingletonClass(const std::string& className);
|
||||
void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
|
||||
|
||||
void registerClassStaticFunction(const std::string& className,
|
||||
@@ -85,6 +85,11 @@ public:
|
||||
}
|
||||
|
||||
// methods for binding functions
|
||||
template<class C, typename F>
|
||||
void bindSingletonFunction(const std::string& functionName, F C::*function, C *instance);
|
||||
template<class C, typename F>
|
||||
void bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance);
|
||||
|
||||
template<class C, typename F>
|
||||
void bindClassStaticFunction(const std::string& functionName, const F& function);
|
||||
template<typename F>
|
||||
@@ -340,6 +345,17 @@ void LuaInterface::polymorphicPush(T v, Args... args) {
|
||||
}
|
||||
|
||||
// next templates must be defined after above includes
|
||||
|
||||
template<class C, typename F>
|
||||
void LuaInterface::bindSingletonFunction(const std::string& functionName, F C::*function, C *instance) {
|
||||
registerClassStaticFunction<C>(functionName, luabinder::bind_singleton_mem_fun(function, instance));
|
||||
}
|
||||
|
||||
template<class C, typename F>
|
||||
void LuaInterface::bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance) {
|
||||
registerClassStaticFunction(className, functionName, luabinder::bind_singleton_mem_fun(function, instance));
|
||||
}
|
||||
|
||||
template<class C, typename F>
|
||||
void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
|
||||
registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
int getUseCount();
|
||||
|
||||
/// Returns the derived class name, its the same name used in Lua
|
||||
std::string getClassName() const {
|
||||
std::string getClassName() {
|
||||
// TODO: this could be cached for more performance
|
||||
return stdext::demangle_name(typeid(*this).name());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user