diff --git a/docs/source/api/simple_usertype.rst b/docs/source/api/simple_usertype.rst index 0447f4a6..dd61b5c6 100644 --- a/docs/source/api/simple_usertype.rst +++ b/docs/source/api/simple_usertype.rst @@ -9,7 +9,7 @@ This type is no different from :doc:`regular usertype`, but with the f * Dot (".") syntax is not natively supported for simple usertypes (e.g., typical member variable / property bindings) - All member variables become functions of that name and are get/set in Lua with the syntax ``local v = obj:value()`` to get, and ``obj:value(24)`` to set - :doc:`properties` also become functions, similar to how member variables are treated above + - ``sol::var`` takes the wrapped up type and pushes it directly into that named slot * Automatic "__index" and "__newindex" handling is not done - Overriding either of these properties leaves it entirely up to you to handle how you find variables - - This includes ``sol::var( ... )``, and similar "dot-access" types - If you override "__index" or "__newindex", you must perform a raw get on the original table and return a valid function / value if you want it to find the members you already set on the ``simple_usertype`` diff --git a/docs/source/api/usertype.rst b/docs/source/api/usertype.rst index f3266696..eb076981 100644 --- a/docs/source/api/usertype.rst +++ b/docs/source/api/usertype.rst @@ -171,8 +171,10 @@ The constructor of usertype takes a variable number of arguments. It takes an ev - Binds a typical member function or variable to ``"{name}"``. In the case of a member variable or member function, ``type`` must be ``T`` or a base of ``T``. * ``"{name}", sol::readonly( &type::member_variable )`` - Binds a typical variable to ``"{name}"``. Similar to the above, but the variable will be read-only, meaning an error will be generated if anything attemps to write to this variable. -* ``"{name}", sol::property( &type::getter_func, &type::setter_func )`` +* ``"{name}", sol::property( getter_func, setter_func )`` - Binds a typical variable to ``"{name}"``, but gets and sets using the specified setter and getter functions. Not that if you do not pass a setter function, the variable will be read-only. Also not that if you do not pass a getter function, it will be write-only. +* ``"{name}", sol::var( some_value )`` or ``"{name}", sol::var( std::ref( some_value ) )`` + - Binds a typical variable to ``"{name}"``, optionally by reference (e.g., refers to the same memory in C++). This is useful for global variables and the like. * ``"{name}", sol::overloaded( Func1, Func2, ... )`` - Creates an oveloaded member function that discriminates on number of arguments and types. * ``sol::base_classes, sol::bases`` diff --git a/docs/source/tutorial/cxx-in-lua.rst b/docs/source/tutorial/cxx-in-lua.rst index 25e38f48..9ce6123b 100644 --- a/docs/source/tutorial/cxx-in-lua.rst +++ b/docs/source/tutorial/cxx-in-lua.rst @@ -124,6 +124,6 @@ To do this, you bind things using the ``new_usertype`` and ``set_usertype`` meth lua.script_file("player_script.lua"); -That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. +That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. You can even bind global variables (even by reference with ``std::ref``) with ``sol::var``. There's a lot to try out! This is a powerful way to allow reuse of C++ code from Lua beyond just registering functions, and should get you on your way to having more complex classes and data structures! In the case that you need more customization than just usertypes, however, you can customize Sol to behave more fit to your desires by using the desired :doc:`customization and extension structures`. \ No newline at end of file diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 66c05bf7..1bf14dac 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -288,6 +288,16 @@ namespace sol { } }; + template + struct pusher> { + static int push(lua_State* L, var_wrapper&& vw) { + return stack::push(L, std::move(vw.value)); + } + static int push(lua_State* L, const var_wrapper& vw) { + return stack::push(L, vw.value); + } + }; + template struct pusher>> { static int push(lua_State* L, detail::tagged>) { diff --git a/test_simple_usertypes.cpp b/test_simple_usertypes.cpp index 3a04ee61..a97e2c3b 100644 --- a/test_simple_usertypes.cpp +++ b/test_simple_usertypes.cpp @@ -209,3 +209,31 @@ TEST_CASE("usertype/simple-shared-ptr-regression", "simple usertype metatables s REQUIRE(created == 1); REQUIRE(destroyed == 1); } + +TEST_CASE("usertypes/simple=vars", "simple usertype vars can bind various values (no ref)") { + int muh_variable = 10; + int through_variable = 25; + + sol::state lua; + lua.open_libraries(); + + struct test {}; + lua.new_simple_usertype("test", + "straight", sol::var(2), + "global", sol::var(muh_variable), + "global2", sol::var(through_variable) + ); + + lua.script(R"( +s = test.straight +g = test.global +g2 = test.global2 +)"); + + int s = lua["s"]; + int g = lua["g"]; + int g2 = lua["g2"]; + REQUIRE(s == 2); + REQUIRE(g == 10); + REQUIRE(g2 == 25); +} diff --git a/test_usertypes.cpp b/test_usertypes.cpp index 9ee3148b..86c64eeb 100644 --- a/test_usertypes.cpp +++ b/test_usertypes.cpp @@ -1207,6 +1207,26 @@ TEST_CASE("usertype/vars", "usertype vars can bind various class items") { "ref_global2", sol::var(std::ref(through_variable)) ); + int prets = lua["test"]["straight"]; + int pretg = lua["test"]["global"]; + int pretrg = lua["test"]["ref_global"]; + int pretg2 = lua["test"]["global2"]; + int pretrg2 = lua["test"]["ref_global2"]; + + REQUIRE(prets == 2); + REQUIRE(pretg == 25); + REQUIRE(pretrg == 25); + REQUIRE(pretg2 == 10); + REQUIRE(pretrg2 == 10); + + lua.script(R"( +print(test.straight) +test.straight = 50 +print(test.straight) +)"); + int s = lua["test"]["straight"]; + REQUIRE(s == 50); + lua.script(R"( t = test.new() print(t.global)