mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
this commit adds support for differentiating between multiple different unique_usertypes without actually having to store type information. It does not include the ability to override a unique_usertype
label for a specific type, but that might not prove necessary if differentiation remains possible with this methodology
Complete fixes #422 and addresses #423
This commit is contained in:
parent
85620df63c
commit
0fb53335c4
|
@ -429,8 +429,16 @@ namespace sol {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int metatableindex = lua_gettop(L);
|
int metatableindex = lua_gettop(L);
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex))
|
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex)) {
|
||||||
return true;
|
void* memory = lua_touserdata(L, 1);
|
||||||
|
T** pointerpointer = static_cast<T**>(memory);
|
||||||
|
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
||||||
|
bool success = &detail::usertype_unique_alloc_destroy<T, X> == pdx;
|
||||||
|
if (!success) {
|
||||||
|
handler(L, index, type::userdata, indextype);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
handler(L, index, type::userdata, indextype);
|
handler(L, index, type::userdata, indextype);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -40,25 +40,26 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct as_value_tag {};
|
struct as_value_tag {};
|
||||||
|
|
||||||
using special_destruct_func = void(*)(void*);
|
using unique_destructor = void(*)(void*);
|
||||||
|
|
||||||
template <typename T, typename Real>
|
|
||||||
inline void special_destruct(void* memory) {
|
|
||||||
T** pointerpointer = static_cast<T**>(memory);
|
|
||||||
special_destruct_func* dx = static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1));
|
|
||||||
Real* target = static_cast<Real*>(static_cast<void*>(dx + 1));
|
|
||||||
target->~Real();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int unique_destruct(lua_State* L) {
|
inline int unique_destruct(lua_State* L) {
|
||||||
void* memory = lua_touserdata(L, 1);
|
void* memory = lua_touserdata(L, 1);
|
||||||
T** pointerpointer = static_cast<T**>(memory);
|
T** pointerpointer = static_cast<T**>(memory);
|
||||||
special_destruct_func& dx = *static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1));
|
unique_destructor& dx = *static_cast<unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
||||||
(dx)(memory);
|
(dx)(memory);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Real>
|
||||||
|
inline void usertype_unique_alloc_destroy(void* memory) {
|
||||||
|
T** pointerpointer = static_cast<T**>(memory);
|
||||||
|
unique_destructor* dx = static_cast<unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
||||||
|
Real* target = static_cast<Real*>(static_cast<void*>(dx + 1));
|
||||||
|
std::allocator<Real> alloc;
|
||||||
|
alloc.destroy(target);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int user_alloc_destroy(lua_State* L) {
|
inline int user_alloc_destroy(lua_State* L) {
|
||||||
void* rawdata = lua_touserdata(L, 1);
|
void* rawdata = lua_touserdata(L, 1);
|
||||||
|
|
|
@ -567,7 +567,7 @@ namespace sol {
|
||||||
static Real& get(lua_State* L, int index, record& tracking) {
|
static Real& get(lua_State* L, int index, record& tracking) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
P** pref = static_cast<P**>(lua_touserdata(L, index));
|
P** pref = static_cast<P**>(lua_touserdata(L, index));
|
||||||
detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1));
|
detail::unique_destructor* fx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
|
||||||
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
||||||
return *mem;
|
return *mem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,10 +153,10 @@ namespace sol {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push_deep(lua_State* L, Args&&... args) {
|
static int push_deep(lua_State* L, Args&&... args) {
|
||||||
P** pref = static_cast<P**>(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real)));
|
P** pref = static_cast<P**>(lua_newuserdata(L, sizeof(P*) + sizeof(detail::unique_destructor) + sizeof(Real)));
|
||||||
detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1));
|
detail::unique_destructor* fx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
|
||||||
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
||||||
*fx = detail::special_destruct<P, Real>;
|
*fx = detail::usertype_unique_alloc_destroy<P, Real>;
|
||||||
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
||||||
*pref = unique_usertype_traits<T>::get(*mem);
|
*pref = unique_usertype_traits<T>::get(*mem);
|
||||||
if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) {
|
if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) {
|
||||||
|
|
|
@ -746,8 +746,8 @@ namespace sol {
|
||||||
bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name;
|
bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name;
|
||||||
if (hasdestructor) {
|
if (hasdestructor) {
|
||||||
ref_table[lastreg - 1] = { nullptr, nullptr };
|
ref_table[lastreg - 1] = { nullptr, nullptr };
|
||||||
unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> };
|
|
||||||
}
|
}
|
||||||
|
unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> };
|
||||||
|
|
||||||
// Now use um
|
// Now use um
|
||||||
const bool& mustindex = umc.mustindex;
|
const bool& mustindex = umc.mustindex;
|
||||||
|
|
|
@ -1137,35 +1137,88 @@ TEST_CASE("functions/set_function-already-wrapped", "setting a function returned
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("functions/unique-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique usertype") {
|
TEST_CASE("functions/unique-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique usertype") {
|
||||||
sol::state lua;
|
struct test {
|
||||||
|
int special_value = 17;
|
||||||
struct test { int special_value = 17; };
|
test() : special_value(17) {}
|
||||||
auto print_up_test = [](std::unique_ptr<test>& x) {
|
test(int special_value) : special_value(special_value) {}
|
||||||
REQUIRE(x->special_value == 17);
|
};
|
||||||
|
auto print_up_test = [](std::unique_ptr<test>& x) {
|
||||||
|
REQUIRE(x->special_value == 21);
|
||||||
|
};
|
||||||
|
auto print_sp_test = [](std::shared_ptr<test>& x) {
|
||||||
|
REQUIRE(x->special_value == 44);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto print_ptr_test = [](test* x) {
|
auto print_ptr_test = [](test* x) {
|
||||||
REQUIRE(x->special_value == 17);
|
REQUIRE(x->special_value == 17);
|
||||||
};
|
};
|
||||||
|
auto print_ref_test = [](test& x) {
|
||||||
|
bool is_any = x.special_value == 17
|
||||||
|
|| x.special_value == 21
|
||||||
|
|| x. special_value == 44;
|
||||||
|
REQUIRE(is_any);
|
||||||
|
};
|
||||||
|
using f_t = void(test&);
|
||||||
|
f_t* fptr = print_ref_test;
|
||||||
|
|
||||||
|
std::unique_ptr<test> ut = std::make_unique<test>(17);
|
||||||
|
SECTION("working") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
lua.set_function("f", print_up_test);
|
lua.set_function("f", print_up_test);
|
||||||
lua.set_function("g", sol::overload(
|
lua.set_function("g", sol::overload(
|
||||||
std::ref(print_up_test),
|
std::move(print_sp_test),
|
||||||
print_ptr_test
|
print_up_test,
|
||||||
|
std::ref(print_ptr_test)
|
||||||
));
|
));
|
||||||
|
lua.set_function("h", std::ref(fptr));
|
||||||
|
|
||||||
|
lua["v1"] = std::make_unique<test>(21);
|
||||||
|
lua["v2"] = std::make_shared<test>(44);
|
||||||
|
lua["v3"] = test(17);
|
||||||
|
lua["v4"] = ut.get();
|
||||||
|
|
||||||
lua["v1"] = std::make_unique<test>();
|
|
||||||
lua["v2"] = test{};
|
|
||||||
REQUIRE_NOTHROW([&]() {
|
|
||||||
lua.script("g(v1)");
|
|
||||||
}());
|
|
||||||
REQUIRE_NOTHROW([&]() {
|
|
||||||
lua.script("g(v2)");
|
|
||||||
}());
|
|
||||||
REQUIRE_NOTHROW([&]() {
|
REQUIRE_NOTHROW([&]() {
|
||||||
lua.script("f(v1)");
|
lua.script("f(v1)");
|
||||||
|
lua.script("g(v1)");
|
||||||
|
lua.script("g(v2)");
|
||||||
|
lua.script("g(v3)");
|
||||||
|
lua.script("g(v4)");
|
||||||
|
lua.script("h(v1)");
|
||||||
|
lua.script("h(v2)");
|
||||||
|
lua.script("h(v3)");
|
||||||
|
lua.script("h(v4)");
|
||||||
}());
|
}());
|
||||||
|
};
|
||||||
|
// LuaJIT segfaults hard on some Linux machines
|
||||||
|
// and it breaks all the tests...
|
||||||
|
SECTION("throws-value") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.set_function("f", print_up_test);
|
||||||
|
lua["v3"] = test(17);
|
||||||
|
|
||||||
|
REQUIRE_THROWS([&]() {
|
||||||
|
lua.script("f(v3)");
|
||||||
|
}());
|
||||||
|
};
|
||||||
|
SECTION("throws-shared_ptr") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.set_function("f", print_up_test);
|
||||||
|
lua["v2"] = std::make_shared<test>(44);
|
||||||
|
|
||||||
REQUIRE_THROWS([&]() {
|
REQUIRE_THROWS([&]() {
|
||||||
lua.script("f(v2)");
|
lua.script("f(v2)");
|
||||||
}());
|
}());
|
||||||
|
};
|
||||||
|
SECTION("throws-ptr") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.set_function("f", print_up_test);
|
||||||
|
lua["v4"] = ut.get();
|
||||||
|
|
||||||
|
REQUIRE_THROWS([&]() {
|
||||||
|
lua.script("f(v4)");
|
||||||
|
}());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user