From bd83b3bb65dfeccf26ccd8f0729c1fbc128659b8 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 4 Nov 2016 19:56:48 -0400 Subject: [PATCH] [ci skip] read only documentation --- docs/source/api/containers.rst | 48 +++++++++++++------------- docs/source/api/readonly.rst | 61 ++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 26 deletions(-) diff --git a/docs/source/api/containers.rst b/docs/source/api/containers.rst index 04649ca5..cfbf6f74 100644 --- a/docs/source/api/containers.rst +++ b/docs/source/api/containers.rst @@ -18,36 +18,36 @@ Here's a complete working example of it working for Lua 5.3 and Lua 5.2, and how lua.open_libraries(); lua.script(R"( - function f (x) - print('--- Calling f ---') - for k, v in ipairs(x) do - print(k, v) + function f (x) + print('--- Calling f ---') + for k, v in ipairs(x) do + print(k, v) + end end - end - )"); + )"); - // Have the function we - // just defined in Lua - sol::function f = lua["f"]; + // Have the function we + // just defined in Lua + sol::function f = lua["f"]; - // Set a global variable called - // "arr" to be a vector of 5 lements - lua["arr"] = std::vector{ 2, 4, 6, 8, 10 }; - - // Call it, see 5 elements - // printed out - f(lua["arr"]); + // Set a global variable called + // "arr" to be a vector of 5 lements + lua["arr"] = std::vector{ 2, 4, 6, 8, 10 }; + + // Call it, see 5 elements + // printed out + f(lua["arr"]); - // Mess with it in C++ - std::vector& reference_to_arr = lua["arr"]; - reference_to_arr.push_back(12); + // Mess with it in C++ + std::vector& reference_to_arr = lua["arr"]; + reference_to_arr.push_back(12); - // Call it, see *6* elements - // printed out - f(lua["arr"]); + // Call it, see *6* elements + // printed out + f(lua["arr"]); - return 0; -} + return 0; + } Note that this will not work well in 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme. diff --git a/docs/source/api/readonly.rst b/docs/source/api/readonly.rst index 3a9517f1..0b85f40a 100644 --- a/docs/source/api/readonly.rst +++ b/docs/source/api/readonly.rst @@ -1,6 +1,6 @@ readonly ======== -Routine to mark a member variable as read-only +routine to mark a member variable as read-only ---------------------------------------------- .. code-block:: cpp @@ -8,4 +8,61 @@ Routine to mark a member variable as read-only template auto readonly( T&& value ); -The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error. +The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error. This can ONLY work on :doc:`usertypes` and when you specifically set a member variable as a function and wrap it with this. It will NOT work anywhere else: doing so will invoke compiler errors. + +If you are looking to make a read-only table, you need to go through a bit of a complicated song and dance by overriding the ``__index`` metamethod. Here's a complete example on the way to do that using ``sol``: + + +.. code-block:: cpp + :caption: read-only.cpp + + #define SOL_CHECK_ARGUMENTS + #include + + #include + + struct object { + void my_func() { + std::cout << "hello\n"; + } + }; + + int deny(lua_State* L) { + return luaL_error(L, "HAH! Deniiiiied!"); + } + + int main() { + sol::state lua; + lua.open_libraries(sol::lib::base); + + object my_obj; + + sol::table obj_table = lua.create_named_table("object"); + + sol::table obj_metatable = lua.create_table_with(); + obj_metatable.set_function("my_func", &object::my_func, &my_obj); + // Set whatever else you need to + // on the obj_metatable, + // not on the obj_table itself! + + // Properly self-index metatable to block things + obj_metatable[sol::meta_function::new_index] = deny; + obj_metatable[sol::meta_function::index] = obj_metatable; + + // Set it on the actual table + obj_table[sol::metatable_key] = obj_metatable; + + try { + lua.script(R"( + print(object.my_func) + object["my_func"] = 24 + print(object.my_func) + )"); + } + catch (const std::exception& e) { + std::cout << e.what() << std::endl; + } + return 0; + } + +It is a verbose example, but it explains everything. Perhaps in the future ``sol2`` may feature a ``create_readonly_table`` abstraction for users!