diff options
Diffstat (limited to '3rdparty/sol2/docs/source/api/metatable_key.rst')
-rw-r--r-- | 3rdparty/sol2/docs/source/api/metatable_key.rst | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/3rdparty/sol2/docs/source/api/metatable_key.rst b/3rdparty/sol2/docs/source/api/metatable_key.rst new file mode 100644 index 00000000000..718eb2b2ffc --- /dev/null +++ b/3rdparty/sol2/docs/source/api/metatable_key.rst @@ -0,0 +1,154 @@ +metatable_key +============= +A key for setting and getting an object's metatable +--------------------------------------------------- + +.. code-block:: cpp + + struct metatable_key_t {}; + const metatable_key_t metatable_key; + +You can use this in conjunction with :doc:`sol::table<table>` to set/get a metatable. Lua metatables are powerful ways to override default behavior of objects for various kinds of operators, among other things. Here is an entirely complete example, showing getting and working with a :doc:`usertype<usertype>`'s metatable defined by Sol: + +.. code-block:: cpp + :caption: messing with metatables + :linenos: + + #include <sol.hpp> + + int main () { + + struct bark { + int operator()(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype<bark>("bark", + sol::meta_function::call_function, &bark::operator() + ); + + bark b; + lua.set("b", &b); + + sol::table b_as_table = lua["b"]; + sol::table b_metatable = b_as_table[sol::metatable_key]; + sol::function b_call = b_metatable["__call"]; + sol::function b_as_function = lua["b"]; + + int result1 = b_as_function(1); + int result2 = b_call(b, 1); + // result1 == result2 == 1 + } + +It's further possible to have a "Dynamic Getter" (`thanks to billw2012 and Nava2 for this example`_!): + +.. code-block:: cpp + :caption: One way to make dynamic properties (there are others!) + :linenos: + + #include <sol.hpp> + #include <unordered_map> + + struct PropertySet { + sol::object get_property_lua(const char* name, sol::this_state s) + { + auto& var = props[name]; + return sol::make_object(s, var); + } + + void set_property_lua(const char* name, sol::stack_object object) + { + props[name] = object.as<std::string>(); + } + + std::unordered_map<std::string, std::string> props; + }; + + struct DynamicObject { + PropertySet& get_dynamic_props() { + return dynamic_props; + } + + PropertySet dynamic_props; + }; + + + int main () { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype<PropertySet>("PropertySet", + sol::meta_function::new_index, &PropertySet::set_property_lua, + sol::meta_function::index, &PropertySet::get_property_lua + ); + + lua.new_usertype<DynamicObject>("DynamicObject", + "props", sol::property(&DynamicObject::get_dynamic_props) + ); + + lua.script(R"( + obj = DynamicObject:new() + obj.props.name = 'test name' + print('name = ' .. obj.props.name) + )"); + + std::string name = lua["obj"]["props"]["name"]; + // name == "test name"; + } + + +You can even manipulate the ability to set and get items using metatable objects on a usertype or similar: + +.. code-block:: cpp + :caption: messing with metatables - vector type + :linenos: + + #include <sol.hpp> + + class vector { + public: + double data[3]; + + vector() : data{ 0,0,0 } {} + + double& operator[](int i) + { + return data[i]; + } + + + static double my_index(vector& v, int i) + { + return v[i]; + } + + static void my_new_index(vector& v, int i, double x) + { + v[i] = x; + } + }; + + int main () { + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(), + sol::meta_function::index, &vector::my_index, + sol::meta_function::new_index, &vector::my_new_index); + lua.script("v = vector.new()\n" + "print(v[1])\n" + "v[2] = 3\n" + "print(v[2])\n" + ); + + vector& v = lua["v"]; + // v[0] == 0.0; + // v[1] == 0.0; + // v[2] == 3.0; + } + + +.. _thanks to billw2012 and Nava2 for this example: https://github.com/ThePhD/sol2/issues/71#issuecomment-225402055
\ No newline at end of file |