mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
okay std::function returns work
i want to use an is_function trait to differentiate classes when they get pushed problem i feel that is_function may capture things not necessarily intended to be function objects right now it is only qualified by pusher<function_t> if change is necessary, then it becomes pusher<T, EnableIf<IsFunction<T>>>
This commit is contained in:
parent
736d354861
commit
3306b44162
148
sol/function.hpp
148
sol/function.hpp
|
@ -26,6 +26,7 @@
|
||||||
#include "tuple.hpp"
|
#include "tuple.hpp"
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
#include "function_types.hpp"
|
#include "function_types.hpp"
|
||||||
|
#include "userdata_traits.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -86,49 +87,48 @@ public:
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template <>
|
template <>
|
||||||
struct pusher<function_t> {
|
struct pusher<function_t> {
|
||||||
template<typename T, typename TFx>
|
|
||||||
void set_isfunction_fx(lua_State* L, std::true_type, T&& key, TFx&& fx) {
|
template<typename TFx>
|
||||||
set_fx(std::false_type(), std::forward<T>(key), std::forward<TFx>(fx));
|
static void set_isfunction_fx(std::true_type, lua_State* L, TFx&& fx) {
|
||||||
|
set_fx(std::false_type(), L, std::forward<TFx>(fx));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx>
|
template<typename TFx>
|
||||||
void set_isfunction_fx(lua_State* L, std::false_type, T&& key, TFx&& fx) {
|
static void set_isfunction_fx(std::false_type, lua_State* L, TFx&& fx) {
|
||||||
typedef Decay<TFx> clean_lambda;
|
typedef Decay<TFx> clean_lambda;
|
||||||
typedef typename function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t;
|
typedef typename function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t;
|
||||||
typedef std::is_convertible<clean_lambda, raw_func_t> isconvertible;
|
typedef std::is_convertible<clean_lambda, raw_func_t> is_convertible;
|
||||||
set_isconvertible_fx(isconvertible(), std::forward<T>(key), std::forward<TFx>(fx));
|
set_isconvertible_fx(is_convertible(), L, std::forward<TFx>(fx));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx>
|
template<typename TFx>
|
||||||
void set_isconvertible_fx(lua_State* L, std::true_type, T&& key, TFx&& fx) {
|
static void set_isconvertible_fx(std::true_type, lua_State* L, TFx&& fx) {
|
||||||
typedef Decay<TFx> clean_lambda;
|
typedef Decay<TFx> clean_lambda;
|
||||||
typedef typename function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t;
|
typedef typename function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t;
|
||||||
set_isfunction_fx(std::true_type(), std::forward<T>(key), raw_func_t(std::forward<TFx>(fx)));
|
set_isfunction_fx(std::true_type(), L, raw_func_t(std::forward<TFx>(fx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx>
|
template<typename TFx>
|
||||||
void set_isconvertible_fx(lua_State* L, std::false_type, T&& key, TFx&& fx) {
|
static void set_isconvertible_fx(std::false_type, lua_State* L, TFx&& fx) {
|
||||||
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
||||||
std::unique_ptr<base_function> sptr(new functor_function<clean_fx>(std::forward<TFx>(fx)));
|
std::unique_ptr<base_function> sptr(new functor_function<clean_fx>(std::forward<TFx>(fx)));
|
||||||
set_fx(std::forward<T>(key), std::move(sptr));
|
set_fx<TFx>(L, std::move(sptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx, typename TObj>
|
template<typename TFx, typename TObj>
|
||||||
void set_lvalue_fx(lua_State* L, std::true_type, T&& key, TFx&& fx, TObj&& obj) {
|
static void set_lvalue_fx(std::true_type, lua_State* L, TFx&& fx, TObj&& obj) {
|
||||||
set_fx(std::true_type(), std::forward<T>(key), std::forward<TFx>(fx), std::forward<TObj>(obj));
|
set_fx(std::true_type(), L, std::forward<TFx>(fx), std::forward<TObj>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx, typename TObj>
|
template<typename TFx, typename TObj>
|
||||||
void set_lvalue_fx(lua_State* L, std::false_type, T&& key, TFx&& fx, TObj&& obj) {
|
static void set_lvalue_fx(std::false_type, lua_State* L, TFx&& fx, TObj&& obj) {
|
||||||
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
||||||
std::unique_ptr<base_function> sptr(new member_function<clean_fx, TObj>(std::forward<TObj>(obj), std::forward<TFx>(fx)));
|
std::unique_ptr<base_function> sptr(new member_function<clean_fx, TObj>(std::forward<TObj>(obj), std::forward<TFx>(fx)));
|
||||||
return set_fx(std::forward<T>(key), std::move(sptr));
|
return set_fx<TFx>(L, std::move(sptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx, typename TObj>
|
template<typename TFx, typename TObj>
|
||||||
void set_fx(lua_State* L, std::true_type, T&& key, TFx&& fx, TObj&& obj) {
|
static void set_fx(std::true_type, lua_State* L, TFx&& fx, TObj&& obj) {
|
||||||
std::string fkey(key);
|
|
||||||
|
|
||||||
// Layout:
|
// Layout:
|
||||||
// idx 1...n: verbatim data of member function pointer
|
// idx 1...n: verbatim data of member function pointer
|
||||||
// idx n + 1: is the object's void pointer
|
// idx n + 1: is the object's void pointer
|
||||||
|
@ -137,85 +137,24 @@ struct pusher<function_t> {
|
||||||
Decay<TFx> fxptr(std::forward<TFx>(fx));
|
Decay<TFx> fxptr(std::forward<TFx>(fx));
|
||||||
void* userobjdata = static_cast<void*>(sol::detail::get_ptr(obj));
|
void* userobjdata = static_cast<void*>(sol::detail::get_ptr(obj));
|
||||||
lua_CFunction freefunc = &static_member_function<Decay<TObj>, TFx>::call;
|
lua_CFunction freefunc = &static_member_function<Decay<TObj>, TFx>::call;
|
||||||
const char* freefuncname = fkey.c_str();
|
|
||||||
const luaL_Reg funcreg[2] = {
|
|
||||||
{ freefuncname, freefunc },
|
|
||||||
{ nullptr, nullptr }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int upvalues = stack::detail::push_as_upvalues(L, fxptr);
|
int upvalues = stack::detail::push_as_upvalues(L, fxptr);
|
||||||
stack::push(L, userobjdata);
|
stack::push(L, userobjdata);
|
||||||
luaL_setfuncs(L, funcreg, upvalues + 1);
|
stack::pusher<lua_CFunction>{}.push(L, freefunc, upvalues);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename TFx>
|
template<typename TFx>
|
||||||
void set_fx(lua_State* L, std::false_type, T&& key, TFx&& fx) {
|
static void set_fx(lua_State* L, std::false_type, TFx&& fx) {
|
||||||
std::string fkey(key);
|
|
||||||
Decay<TFx> target(std::forward<TFx>(fx));
|
Decay<TFx> target(std::forward<TFx>(fx));
|
||||||
lua_CFunction freefunc = &static_function<TFx>::call;
|
lua_CFunction freefunc = &static_function<TFx>::call;
|
||||||
const char* freefuncname = fkey.c_str();
|
|
||||||
const luaL_Reg funcreg[2] = {
|
|
||||||
{ freefuncname, freefunc },
|
|
||||||
{ nullptr, nullptr }
|
|
||||||
};
|
|
||||||
|
|
||||||
int upvalues = stack::detail::push_as_upvalues(L, target);
|
int upvalues = stack::detail::push_as_upvalues(L, target);
|
||||||
luaL_setfuncs(L, funcreg, upvalues);
|
stack::pusher<lua_CFunction>{}.push(L, freefunc, upvalues);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename TFx>
|
||||||
void set_fx(lua_State* L, T&& key, std::unique_ptr<base_function> luafunc) {
|
static void set_fx(lua_State* L, std::unique_ptr<base_function> luafunc) {
|
||||||
std::string fkey(key);
|
auto&& metakey = userdata_traits<Unqualified<TFx>>::metatable;
|
||||||
std::string metakey("sol.stateful.");
|
|
||||||
metakey += fkey;
|
|
||||||
metakey += ".meta";
|
|
||||||
base_function* target = luafunc.release();
|
|
||||||
void* userdata = reinterpret_cast<void*>(target);
|
|
||||||
lua_CFunction freefunc = &base_function::call;
|
|
||||||
const char* freefuncname = fkey.c_str();
|
|
||||||
const char* metatablename = metakey.c_str();
|
|
||||||
const luaL_Reg funcreg[2] = {
|
|
||||||
{ freefuncname, freefunc },
|
|
||||||
{ nullptr, nullptr }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (luaL_newmetatable(L, metatablename) == 1) {
|
|
||||||
lua_pushstring(L, "__gc");
|
|
||||||
lua_pushcclosure(L, &base_function::gc, 0);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
|
|
||||||
stack::detail::push_userdata(L, userdata, metatablename);
|
|
||||||
luaL_setfuncs(L, funcreg, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename TFx>
|
|
||||||
void set_function(T&& key, TFx&& fx) {
|
|
||||||
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
|
||||||
set_isfunction_fx(std::is_function<clean_fx>(), std::forward<T>(key), std::forward<TFx>(fx));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename TFx, typename TObj>
|
|
||||||
void set_function(T&& key, TFx&& fx, TObj&& obj) {
|
|
||||||
set_lvalue_fx(Bool<std::is_lvalue_reference<TObj>::value || std::is_pointer<TObj>::value>(),
|
|
||||||
std::forward<T>(key), std::forward<TFx>(fx), std::forward<TObj>(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Key, typename... Args>
|
|
||||||
void push(lua_State* L, Key&& key, Args&&... args) {
|
|
||||||
set_function(L, std::forward<Key>(key), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
template <typename Signature>
|
|
||||||
struct pusher<std::function<Signature>> {
|
|
||||||
typedef std::function<Signature> fx_t;
|
|
||||||
|
|
||||||
static void push_fx(lua_State* L, std::unique_ptr<base_function> luafunc) {
|
|
||||||
auto&& metakey = userdata_traits<fx_t>::metatable;
|
|
||||||
const char* metatablename = std::addressof(metakey[0]);
|
const char* metatablename = std::addressof(metakey[0]);
|
||||||
base_function* target = luafunc.release();
|
base_function* target = luafunc.release();
|
||||||
void* userdata = reinterpret_cast<void*>(target);
|
void* userdata = reinterpret_cast<void*>(target);
|
||||||
|
@ -223,17 +162,36 @@ struct pusher<std::function<Signature>> {
|
||||||
|
|
||||||
if (luaL_newmetatable(L, metatablename) == 1) {
|
if (luaL_newmetatable(L, metatablename) == 1) {
|
||||||
lua_pushstring(L, "__gc");
|
lua_pushstring(L, "__gc");
|
||||||
lua_pushcclosure(L, &base_function::gc, 0);
|
stack::push(L, &base_function::gc);
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
stack::detail::push_userdata(L, userdata, metatablename);
|
stack::detail::push_userdata(L, userdata, metatablename);
|
||||||
lua_pushcclosure(L, freefunc, 1);
|
stack::pusher<lua_CFunction>{}.push(L, freefunc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename TFx>
|
||||||
|
static void set_function(lua_State* L, TFx&& fx) {
|
||||||
|
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
|
||||||
|
set_isfunction_fx(std::is_function<clean_fx>(), L, std::forward<TFx>(fx));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TFx, typename TObj>
|
||||||
|
static void set_function(lua_State* L, TFx&& fx, TObj&& obj) {
|
||||||
|
set_lvalue_fx(Bool<std::is_lvalue_reference<TObj>::value || std::is_pointer<TObj>::value>(),
|
||||||
|
L, std::forward<TFx>(fx), std::forward<TObj>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static void push(lua_State* L, Args&&... args) {
|
||||||
|
set_function(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Signature>
|
||||||
|
struct pusher<std::function<Signature>> {
|
||||||
static void push(lua_State* L, std::function<Signature> fx) {
|
static void push(lua_State* L, std::function<Signature> fx) {
|
||||||
std::unique_ptr<base_function> sptr(new functor_function<fx_t>(std::move(fx)));
|
pusher<function_t>{}.push(L, std::move(fx));
|
||||||
push_fx(L, std::move(sptr));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user