diff --git a/sol/container_usertype_metatable.hpp b/sol/container_usertype_metatable.hpp index 0d876b60..a07b85be 100644 --- a/sol/container_usertype_metatable.hpp +++ b/sol/container_usertype_metatable.hpp @@ -105,7 +105,7 @@ namespace sol { if (k <= src.size() && k > 0) { --k; std::advance(it, k); - return stack::push(L, *it); + return stack::push_reference(L, *it); } } return stack::push(L, nil); @@ -115,7 +115,7 @@ namespace sol { K k = stack::get(L, 2); --k; std::advance(it, k); - return stack::push(L, *it); + return stack::push_reference(L, *it); #endif // Safety } @@ -164,8 +164,7 @@ namespace sol { if (it == end(source)) { return 0; } - int p = stack::push(L, k + 1); - p += stack::push(L, *it); + int p = stack::multi_push_reference(L, k + 1, *it); std::advance(it, 1); return p; } @@ -262,7 +261,7 @@ namespace sol { auto it = detail::find(src, *k); if (it != end(src)) { auto& v = *it; - return stack::push(L, v.second); + return stack::push_reference(L, v.second); } } return stack::push(L, nil); diff --git a/sol/simple_usertype_metatable.hpp b/sol/simple_usertype_metatable.hpp index 0969e972..586e0d18 100644 --- a/sol/simple_usertype_metatable.hpp +++ b/sol/simple_usertype_metatable.hpp @@ -282,7 +282,7 @@ namespace sol { indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(false), secondarymeta(false) { + mustindex(true), secondarymeta(true) { (void)detail::swallow{ 0, (add(L, detail::forward_get(args), detail::forward_get(args)),0)... }; diff --git a/test_containers.cpp b/test_containers.cpp index d2e97567..015fbd20 100644 --- a/test_containers.cpp +++ b/test_containers.cpp @@ -272,3 +272,39 @@ TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable REQUIRE(c.get("name") == "Rapptz"); REQUIRE(c.get("project") == "sol"); } + +TEST_CASE("containers/usertype-transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") { + class A { + public: + int a; + A(int b = 2) : a(b) {}; + + void func() { } + }; + + struct B { + + B() { + for (std::size_t i = 0; i < 20; ++i) { + a_list.emplace_back(static_cast(i)); + } + } + + std::vector a_list; + }; + + sol::state lua; + lua.new_usertype("B", + "a_list", &B::a_list + ); + + lua.script(R"( +b = B.new() +a_ref = b.a_list[2] +)"); + + B& b = lua["b"]; + A& a_ref = lua["a_ref"]; + REQUIRE(&b.a_list[1] == &a_ref); + REQUIRE(b.a_list[1].a == a_ref.a); +} diff --git a/test_simple_usertypes.cpp b/test_simple_usertypes.cpp index d8e150d3..4683aa3b 100644 --- a/test_simple_usertypes.cpp +++ b/test_simple_usertypes.cpp @@ -437,3 +437,23 @@ TEST_CASE("usertype/simple-destruction-test", "make sure usertypes are properly lua["testCrash"](); } } + +TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta table also affects the internal function table for pointers as well") { + struct A { + int func() { + return 5000; + } + }; + + sol::state lua; + lua.open_libraries(); + + lua.new_simple_usertype("A"); + sol::table table = lua["A"]; + table["func"] = &A::func; + A a; + lua.set("a", &a); + REQUIRE_NOTHROW( + lua.script("assert(a:func() == 5000)") + ); +}