mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
distinction between "light user data" "user data" and "upvalue", as they are not the same thing
a lua upvalue can be lightuserdata, userdata, or anything else that can have its address taken (it's immediately popped of the stack and carted around with function call) a lightuserdata can only be a pointer (void*) a regular userdata can be anything, but is stored as void* because of "anything" semantics and C heritage of lua upvalues deserve to use the `lua_upvalueindex(n)` macro: lightuserdata/userdata does not (must not) go through this process
This commit is contained in:
parent
77901bb654
commit
736d354861
|
@ -25,8 +25,10 @@
|
|||
#include "reference.hpp"
|
||||
#include "tuple.hpp"
|
||||
#include "stack.hpp"
|
||||
#include "function_types.hpp"
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
class function : public reference {
|
||||
|
@ -133,7 +135,7 @@ struct pusher<function_t> {
|
|||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
Decay<TFx> fxptr(std::forward<TFx>(fx));
|
||||
void* userobjdata = static_cast<void*>(detail::get_ptr(obj));
|
||||
void* userobjdata = static_cast<void*>(sol::detail::get_ptr(obj));
|
||||
lua_CFunction freefunc = &static_member_function<Decay<TObj>, TFx>::call;
|
||||
const char* freefuncname = fkey.c_str();
|
||||
const luaL_Reg funcreg[2] = {
|
||||
|
@ -210,7 +212,29 @@ struct pusher<function_t> {
|
|||
};
|
||||
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]);
|
||||
base_function* target = luafunc.release();
|
||||
void* userdata = reinterpret_cast<void*>(target);
|
||||
lua_CFunction freefunc = &base_function::call;
|
||||
|
||||
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);
|
||||
lua_pushcclosure(L, freefunc, 1);
|
||||
}
|
||||
|
||||
static void push(lua_State* L, std::function<Signature> fx) {
|
||||
std::unique_ptr<base_function> sptr(new functor_function<fx_t>(std::move(fx)));
|
||||
push_fx(L, std::move(sptr));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Signature>
|
||||
|
|
|
@ -167,7 +167,7 @@ struct base_function {
|
|||
}
|
||||
|
||||
static int call(lua_State* L) {
|
||||
void** pinheritancedata = static_cast<void**>(stack::get<lightuserdata_t>(L, 1).value);
|
||||
void** pinheritancedata = static_cast<void**>(stack::get<upvalue_t>(L, 1).value);
|
||||
return base_call(L, *pinheritancedata);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,10 @@ T* get_ptr(T* val) {
|
|||
|
||||
namespace stack {
|
||||
namespace detail {
|
||||
template<typename T, typename Key>
|
||||
template<typename T, typename Key, typename U = Unqualified<T>>
|
||||
inline void push_userdata(lua_State* L, T&& userdata, Key&& metatablekey) {
|
||||
T* pdatum = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
|
||||
T& datum = *pdatum;
|
||||
datum = std::forward<T>(userdata);
|
||||
U* pdatum = static_cast<U*>(lua_newuserdata(L, sizeof(U)));
|
||||
new(pdatum)U(std::forward<T>(userdata));
|
||||
luaL_getmetatable(L, std::addressof(metatablekey[0]));
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
@ -149,6 +148,13 @@ struct getter<userdata_t> {
|
|||
template <>
|
||||
struct getter<lightuserdata_t> {
|
||||
lightuserdata_t get(lua_State* L, int index = 1) {
|
||||
return{ lua_touserdata(L, index) };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<upvalue_t> {
|
||||
upvalue_t get(lua_State* L, int index = 1) {
|
||||
return{ lua_touserdata(L, lua_upvalueindex(index)) };
|
||||
}
|
||||
};
|
||||
|
@ -216,8 +222,8 @@ struct pusher<nil_t> {
|
|||
|
||||
template<>
|
||||
struct pusher<lua_CFunction> {
|
||||
static void push(lua_State* L, lua_CFunction func) {
|
||||
lua_pushcfunction(L, func);
|
||||
static void push(lua_State* L, lua_CFunction func, int n = 0) {
|
||||
lua_pushcclosure(L, func, n);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -228,6 +234,13 @@ struct pusher<void*> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<upvalue_t> {
|
||||
static void push(lua_State* L, upvalue_t upvalue) {
|
||||
lua_pushlightuserdata(L, upvalue);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<lightuserdata_t> {
|
||||
static void push(lua_State* L, lightuserdata_t userdata) {
|
||||
|
@ -235,6 +248,15 @@ struct pusher<lightuserdata_t> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<userdata_t> {
|
||||
template <typename T, typename U = Unqualified<T>>
|
||||
static void push(lua_State* L, T&& data) {
|
||||
U* userdata = static_cast<U*>(lua_newuserdata(L, sizeof(U)));
|
||||
new(userdata)U(std::forward<T>(data));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<const char*> {
|
||||
static void push(lua_State* L, const char* str) {
|
||||
|
@ -293,7 +315,7 @@ inline int push_as_upvalues(lua_State* L, T& item) {
|
|||
data_t data{{}};
|
||||
std::memcpy(std::addressof(data[0]), std::addressof(item), itemsize);
|
||||
for (auto&& v : data) {
|
||||
push(L, v);
|
||||
push(L, upvalue_t(v));
|
||||
}
|
||||
return data_t_count;
|
||||
}
|
||||
|
@ -304,7 +326,7 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
|||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata{ {} };
|
||||
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[ i ] = get<lightuserdata_t>(L, index++);
|
||||
voiddata[ i ] = get<upvalue_t>(L, index++);
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,13 @@ const nil_t nil {};
|
|||
struct void_type {};
|
||||
const void_type Void {};
|
||||
struct function_t {};
|
||||
struct lightuserdata_t {
|
||||
struct upvalue_t {
|
||||
void* value;
|
||||
upvalue_t(void* data) : value(data) {}
|
||||
operator void* () const { return value; }
|
||||
};
|
||||
|
||||
struct lightuserdata_t {
|
||||
void* value;
|
||||
lightuserdata_t(void* data) : value(data) {}
|
||||
operator void* () const { return value; }
|
||||
|
|
Loading…
Reference in New Issue
Block a user