mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
At least I have users who can help me catch my dumbness. One day, I'll find someone who wants to work on something and isn't somehow insufferable.
This commit is contained in:
parent
5740566ecf
commit
6b85ed2936
|
@ -286,15 +286,15 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Lists>
|
template <typename T, typename... Lists>
|
||||||
struct pusher<detail::constructors_for<T, constructor_list<Lists...>>> {
|
struct pusher<detail::tagged<T, constructor_list<Lists...>>> {
|
||||||
static int push(lua_State* L, detail::constructors_for<T, constructor_list<Lists...>>) {
|
static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {
|
||||||
lua_CFunction cf = call_detail::construct<T, Lists...>;
|
lua_CFunction cf = call_detail::construct<T, Lists...>;
|
||||||
return stack::push(L, cf);
|
return stack::push(L, cf);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Fxs>
|
template <typename T, typename... Fxs>
|
||||||
struct pusher<detail::constructors_for<T, constructor_wrapper<Fxs...>>> {
|
struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
|
||||||
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
|
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
|
||||||
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
|
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
|
||||||
int closures = stack::push<user<T>>(L, std::move(c));
|
int closures = stack::push<user<T>>(L, std::move(c));
|
||||||
|
@ -302,6 +302,23 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct pusher<detail::tagged<T, destructor_wrapper<void>>> {
|
||||||
|
static int push(lua_State* L, detail::tagged<T, destructor_wrapper<void>>) {
|
||||||
|
lua_CFunction cf = call_detail::destruct<T>;
|
||||||
|
return stack::push(L, cf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Fx>
|
||||||
|
struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
|
||||||
|
static int push(lua_State* L, destructor_wrapper<Fx> c) {
|
||||||
|
lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>;
|
||||||
|
int closures = stack::push<user<T>>(L, std::move(c));
|
||||||
|
return stack::push(L, c_closure(cf, closures));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // stack
|
} // stack
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename List>
|
template <typename T, typename List>
|
||||||
struct constructors_for {
|
struct tagged {
|
||||||
List l;
|
List l;
|
||||||
};
|
};
|
||||||
} // detail
|
} // detail
|
||||||
|
|
|
@ -36,19 +36,24 @@ namespace sol {
|
||||||
std::vector<std::pair<object, object>> registrations;
|
std::vector<std::pair<object, object>> registrations;
|
||||||
object callconstructfunc;
|
object callconstructfunc;
|
||||||
|
|
||||||
template <typename N, typename F>
|
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
|
void add(lua_State* L, N&& n, F&& f) {
|
||||||
|
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, function_args(std::forward<F>(f))));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
void add(lua_State* L, N&& n, F&& f) {
|
void add(lua_State* L, N&& n, F&& f) {
|
||||||
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, std::forward<F>(f)));
|
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, std::forward<F>(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename... Fxs>
|
template <typename N, typename... Fxs>
|
||||||
void add(lua_State* L, N&& n, constructor_wrapper<Fxs...> c) {
|
void add(lua_State* L, N&& n, constructor_wrapper<Fxs...> c) {
|
||||||
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, detail::constructors_for<T, constructor_wrapper<Fxs...>>{std::move(c)}));
|
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, detail::tagged<T, constructor_wrapper<Fxs...>>{std::move(c)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename... Lists>
|
template <typename N, typename... Lists>
|
||||||
void add(lua_State* L, N&& n, constructor_list<Lists...> c) {
|
void add(lua_State* L, N&& n, constructor_list<Lists...> c) {
|
||||||
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, detail::constructors_for<T, constructor_list<Lists...>>{std::move(c)}));
|
registrations.emplace_back(make_object(L, std::forward<N>(n)), make_object(L, detail::tagged<T, constructor_list<Lists...>>{std::move(c)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
|
@ -123,6 +128,22 @@ namespace sol {
|
||||||
luaL_newmetatable(L, metakey);
|
luaL_newmetatable(L, metakey);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
for (auto& kvp : umx.registrations) {
|
for (auto& kvp : umx.registrations) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
if (kvp.first.template is<std::string>() && kvp.first.template as<std::string>() == "__gc") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (kvp.first.template is<std::string>() && kvp.first.template as<std::string>() == "__gc") {
|
||||||
|
stack::set_field(L, kvp.first, detail::unique_destruct<T>, t.stack_index());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
stack::set_field(L, kvp.first, kvp.second, t.stack_index());
|
stack::set_field(L, kvp.first, kvp.second, t.stack_index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -349,10 +349,12 @@ namespace sol {
|
||||||
(void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... };
|
(void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... };
|
||||||
um.finish_regs(value_table, lastreg);
|
um.finish_regs(value_table, lastreg);
|
||||||
value_table[lastreg] = { nullptr, nullptr };
|
value_table[lastreg] = { nullptr, nullptr };
|
||||||
|
bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name;
|
||||||
regs_t ref_table = value_table;
|
regs_t ref_table = value_table;
|
||||||
bool hasdestructor = lastreg > 0 && name_of(meta_function::garbage_collect) == ref_table[lastreg - 1].name;
|
regs_t unique_table = value_table;
|
||||||
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> };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now use um
|
// Now use um
|
||||||
|
@ -360,27 +362,26 @@ namespace sol {
|
||||||
for (std::size_t i = 0; i < 3; ++i) {
|
for (std::size_t i = 0; i < 3; ++i) {
|
||||||
// Pointer types, AKA "references" from C++
|
// Pointer types, AKA "references" from C++
|
||||||
const char* metakey = nullptr;
|
const char* metakey = nullptr;
|
||||||
|
luaL_Reg* metaregs = nullptr;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
metakey = &usertype_traits<T*>::metatable[0];
|
metakey = &usertype_traits<T*>::metatable[0];
|
||||||
|
metaregs = ref_table.data();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
||||||
|
metaregs = unique_table.data();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
default:
|
default:
|
||||||
metakey = &usertype_traits<T>::metatable[0];
|
metakey = &usertype_traits<T>::metatable[0];
|
||||||
|
metaregs = value_table.data();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
luaL_newmetatable(L, metakey);
|
luaL_newmetatable(L, metakey);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
stack::push(L, make_light(um));
|
stack::push(L, make_light(um));
|
||||||
if (i < 2) {
|
luaL_setfuncs(L, metaregs, 1);
|
||||||
luaL_setfuncs(L, ref_table.data(), 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
luaL_setfuncs(L, value_table.data(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (um.baseclasscheck != nullptr) {
|
if (um.baseclasscheck != nullptr) {
|
||||||
stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index());
|
stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index());
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
TEST_CASE("usertypes/simple_usertypes", "Ensure that simple usertypes properly work here") {
|
TEST_CASE("usertypes/simple-usertypes", "Ensure that simple usertypes properly work here") {
|
||||||
struct marker {
|
struct marker {
|
||||||
bool value = false;
|
bool value = false;
|
||||||
};
|
};
|
||||||
|
@ -170,3 +172,40 @@ TEST_CASE("usertypes/simple-usertypes-constructors", "Ensure that calls with spe
|
||||||
REQUIRE(z == 29);
|
REQUIRE(z == 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/simple-shared-ptr-regression", "simple usertype metatables should not screw over unique usertype metatables") {
|
||||||
|
static int created = 0;
|
||||||
|
static int destroyed = 0;
|
||||||
|
struct test {
|
||||||
|
test() {
|
||||||
|
++created;
|
||||||
|
}
|
||||||
|
|
||||||
|
~test() {
|
||||||
|
++destroyed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
{
|
||||||
|
std::list<std::shared_ptr<test>> tests;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
|
||||||
|
lua.new_simple_usertype<test>("test",
|
||||||
|
"create", [&]() -> std::shared_ptr<test> {
|
||||||
|
tests.push_back(std::make_shared<test>());
|
||||||
|
return tests.back();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
REQUIRE(created == 0);
|
||||||
|
REQUIRE(destroyed == 0);
|
||||||
|
lua.script("x = test.create()");
|
||||||
|
REQUIRE(created == 1);
|
||||||
|
REQUIRE(destroyed == 0);
|
||||||
|
REQUIRE_FALSE(tests.empty());
|
||||||
|
std::shared_ptr<test>& x = lua["x"];
|
||||||
|
std::size_t xuse = x.use_count();
|
||||||
|
std::size_t tuse = tests.back().use_count();
|
||||||
|
REQUIRE(xuse == tuse);
|
||||||
|
}
|
||||||
|
REQUIRE(created == 1);
|
||||||
|
REQUIRE(destroyed == 1);
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
struct vars {
|
struct vars {
|
||||||
|
@ -1085,3 +1087,41 @@ value = pcall(pm.gen,pm)
|
||||||
bool value = lua["value"];
|
bool value = lua["value"];
|
||||||
REQUIRE_FALSE(value);
|
REQUIRE_FALSE(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not screw over unique usertype metatables") {
|
||||||
|
static int created = 0;
|
||||||
|
static int destroyed = 0;
|
||||||
|
struct test {
|
||||||
|
test() {
|
||||||
|
++created;
|
||||||
|
}
|
||||||
|
|
||||||
|
~test() {
|
||||||
|
++destroyed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
{
|
||||||
|
std::list<std::shared_ptr<test>> tests;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
|
||||||
|
lua.new_usertype<test>("test",
|
||||||
|
"create", [&]() -> std::shared_ptr<test> {
|
||||||
|
tests.push_back(std::make_shared<test>());
|
||||||
|
return tests.back();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
REQUIRE(created == 0);
|
||||||
|
REQUIRE(destroyed == 0);
|
||||||
|
lua.script("x = test.create()");
|
||||||
|
REQUIRE(created == 1);
|
||||||
|
REQUIRE(destroyed == 0);
|
||||||
|
REQUIRE_FALSE(tests.empty());
|
||||||
|
std::shared_ptr<test>& x = lua["x"];
|
||||||
|
std::size_t xuse = x.use_count();
|
||||||
|
std::size_t tuse = tests.back().use_count();
|
||||||
|
REQUIRE(xuse == tuse);
|
||||||
|
}
|
||||||
|
REQUIRE(created == 1);
|
||||||
|
REQUIRE(destroyed == 1);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user