diff options
Diffstat (limited to '3rdparty/sol2/docs/source/tutorial/all-the-things.rst')
-rw-r--r-- | 3rdparty/sol2/docs/source/tutorial/all-the-things.rst | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst deleted file mode 100644 index 3b764b8d2e9..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst +++ /dev/null @@ -1,628 +0,0 @@ -tutorial: quick 'n' dirty -========================= - -These are all the things. Use your browser's search to find things you want. - -You'll need to ``#include <sol.hpp>``/``#include "sol.hpp"`` somewhere in your code. Sol is header-only, so you don't need to compile anything. - -opening a state ---------------- - -.. code-block:: cpp - - int main (int argc, char* argv[]) { - sol::state lua; - // open some common libraries - lua.open_libraries(sol::lib::base, sol::lib::package); - lua.script( "print('bark bark bark!')" ); - } - - -sol::state on lua_State* ------------------------- - -For your system/game that already has lua, but you'd like something nice: - -.. code-block:: cpp - - int pre_existing_system( lua_State* L ) { - sol::state_view lua(L); - lua.script( "print('bark bark bark!')" ); - return 0; - } - - -running lua code ----------------- - -.. code-block:: cpp - - sol::state lua; - // load and execute from string - lua.script("a = 'test'"); - // load and execute from file - lua.script_file("path/to/luascript.lua"); - - // run a script, get the result - int value = lua.script("return 54"); - // value == 54 - -To check the success of a loading operation: - -.. code-block:: cpp - - // load file without execute - sol::load_result script1 = lua.load_file("path/to/luascript.lua"); - script1(); //execute - // load string without execute - sol::load_result script2 = lua.load("a = 'test'"); - script2(); //execute - - sol::load_result script3 = lua.load("return 24"); - int value2 = script3(); // execute, get return value - // value2 == 24 - - -To check whether a script was successfully run or not (after loading is assumed to be successful): - -.. code-block:: cpp - - // execute and return result - sol::protected_function_result result1 = lua.do_string("return 24"); - if (result1.valid()) { - int value = result1; - // value == 24 - // yay! - } - else { - // ahhh :c - } - - -There is also ``lua.do_file("path/to/luascript.lua");``. - -set and get variables ---------------------- - -You can set/get everything. - -.. code-block:: cpp - - sol::lua_state lua; - - lua.open_libraries(sol::lib::base); - - // integer types - lua.set("number", 24); - - // floating point numbers - lua["number2"] = 24.5; - - // string types - lua["important_string"] = "woof woof"; - - // non-recognized types is stored as userdata - // is callable, therefore gets stored as a function - lua["a_function"] = [](){ return 100; }; - - // make a table - lua["some_table"] = lua.create_table_wth("value", 24); - - -Equivalent to loading a lua file with: - -.. code-block:: lua - - number = 24 - number2 = 24.5 - important_string = "woof woof" - a_function = function () return 100 end - some_table = { value = 24 } - -Retrieve these variables using this syntax: - -.. code-block:: cpp - - // implicit conversion - int number = lua["number"]; - - // explicit get - auto number2 = lua.get<double>("number2"); - - // strings too - std::string important_string = lua["important_string"]; - - // dig into a table - int value = lua["some_table"]["value"]; - - // get a function - sol::function a_function = lua["a_function"]; - int value_is_100 = a_function(); - - // get a std::function - std::function<int()> a_std_function = lua["a_function"]; - int value_is_still_100 = a_std_function(); - -Retrieve Lua types using ``object`` and other ``sol::`` types. - -.. code-block:: cpp - - sol::state lua; - - // ... everything from before - - sol::object number_obj = lua.get<sol::object>( "number" ); - // sol::type::number - sol::type t1 = number_obj.get_type(); - - sol::object function_obj = lua[ "a_function" ]; - // sol::type::function - sol::type t2 = function_obj.get_type(); - bool is_it_really = function_obj.is<std::function<int()>>(); // true - - // will not contain data - sol::optional<int> check_for_me = lua["a_function"]; - - -You can erase things by setting it to ``nullptr`` or ``sol::nil``. - -.. code-block:: cpp - - sol::state lua; - - lua.script("exists = 250"); - - int first_try = lua.get_or( "exists", 322 ); - // first_try == 250 - - lua.set("exists", sol::nil); - int second_try = lua.get_or( "exists", 322 ); - // second_try == 322 - - -Note that if its a :doc:`userdata/usertype<../api/usertype>` for a C++ type, the destructor will run only when the garbage collector deems it appropriate to destroy the memory. If you are relying on the destructor being run when its set to ``sol::nil``, you're probably committing a mistake. - -tables ------- - -:doc:`sol::state<../api/state>` is a table too. - -.. code-block:: cpp - - sol::state lua; - - // Raw string literal for easy multiline - lua.script( R"( - abc = { [0] = 24 } - def = { - ghi = { - bark = 50, - woof = abc - } - } - )" - ); - - sol::table abc = lua["abc"]; - sol::table def = lua["def"]; - sol::table ghi = lua["def"]["ghi"]; - - int bark1 = def["ghi"]["bark"]; - int bark2 = lua["def"]["ghi"]["bark"]; - // bark1 == bark2 == 50 - - int abcval1 = abc[0]; - int abcval2 = ghi["woof"][0]; - // abcval1 == abcval2 == 24 - -If you're going deep, be safe: - -.. code-block:: cpp - - sol::state lua; - - sol::optional<int> will_not_error = lua["abc"]["DOESNOTEXIST"]["ghi"]; - // will_not_error == sol::nullopt - int also_will_not_error = lua["abc"]["def"]["ghi"]["jklm"].get_or(25); - // is 25 - - // if you don't go safe, - // will throw (or do at_panic if no exceptions) - int aaaahhh = lua["boom"]["the_dynamite"]; - - -make tables ------------ - -Make some: - -.. code-block:: cpp - - sol::state lua; - - lua["abc"] = lua.create_table_with( - 0, 24 - ); - - lua.create_named_table("def", - "ghi", lua.create_table_with( - "bark", 50, - // can reference other existing stuff too - "woof", lua["abc"] - ) - ); - -Equivalent Lua code: - -.. code-block:: lua - - abc = { [0] = 24 } - def = { - ghi = { - bark = 50, - woof = abc - } - } - - -You can put anything you want in tables as values or keys, including strings, numbers, functions, other tables. - -Note that this idea that things can be nested is important and will help later when you get into :ref:`namespacing<namespacing>`. - - -functions ---------- - -They're great. Use them: - -.. code-block:: cpp - - sol::state lua; - - lua.script("function f (a, b, c, d) return 1 end"); - lua.script("function g (a, b) return a + b end"); - - // fixed signature std::function<...> - std::function<int(int, double, int, std::string)> stdfx = lua["f"]; - // sol::function is often easier: - // takes a variable number/types of arguments... - sol::function fx = lua["f"]; - - int is_one = stdfx(1, 34.5, 3, "bark"); - int is_also_one = fx(1, "boop", 3, "bark"); - - // call through operator[] - int is_three = lua["g"](1, 2); - // is_three == 3 - double is_4_8 = lua["g"](2.4, 2.4); - // is_4_8 == 4.8 - -If you need to protect against errors and parser problems and you're not ready to deal with Lua's `longjmp` problems (if you compiled with C), use :doc:`sol::protected_function<../api/protected_function>`. - -You can bind member variables as functions too, as well as all KINDS of function-like things: - -.. code-block:: cpp - - void some_function () { - std::cout << "some function!" << std::endl; - } - - void some_other_function () { - std::cout << "some other function!" << std::endl; - } - - struct some_class { - int variable = 30; - - double member_function () { - return 24.5; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - // put an instance of "some_class" into lua - // (we'll go into more detail about this later - // just know here that it works and is - // put into lua as a userdata - lua.set("sc", some_class()); - - // binds a plain function - lua["f1"] = some_function; - lua.set_function("f2", &some_other_function); - - // binds just the member function - lua["m1"] = &some_class::member_function; - - // binds the class to the type - lua.set_function("m2", &some_class::member_function, some_class{}); - - // binds just the member variable as a function - lua["v1"] = &some_class::variable; - - // binds class with member variable as function - lua.set_function("v2", &some_class::variable, some_class{}); - -The lua code to call these things is: - -.. code-block:: lua - - f1() -- some function! - f2() -- some other function! - - -- need class instance if you don't bind it with the function - print(m1(sc)) -- 24.5 - -- does not need class instance: was bound to lua with one - print(m2()) -- 24.5 - - -- need class instance if you - -- don't bind it with the function - print(v1(sc)) -- 30 - -- does not need class instance: - -- it was bound with one - print(v2()) -- 30 - - -- can set, still - -- requires instance - v1(sc, 212) - -- can set, does not need - -- class instance: was bound with one - v2(254) - - print(v1(sc)) -- 212 - print(v2()) -- 254 - -Can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it. - - -self call ---------- - -You can pass the 'self' argument through C++ to emulate 'member function' calls in Lua. - -.. code-block:: cpp - - sol::state lua; - - lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table); - - // a small script using 'self' syntax - lua.script(R"( - some_table = { some_val = 100 } - - function some_table:add_to_some_val(value) - self.some_val = self.some_val + value - end - - function print_some_val() - print("some_table.some_val = " .. some_table.some_val) - end - )"); - - // do some printing - lua["print_some_val"](); - // 100 - - sol::table self = lua["some_table"]; - self["add_to_some_val"](self, 10); - lua["print_some_val"](); - - - -multiple returns from lua -------------------------- - -.. code-block:: cpp - - sol::state lua; - - lua.script("function f (a, b, c) return a, b, c end"); - - std::tuple<int, int, int> result; - result = lua["f"](100, 200, 300); - // result == { 100, 200, 300 } - int a; - int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); - // a == 100 - // b == 200 - // c == "bark" - - -multiple returns to lua ------------------------ - -.. code-block:: cpp - - sol::state lua; - - lua["f"] = [](int a, int b, sol::object c) { - // sol::object can be anything here: just pass it through - return std::make_tuple( a, b, c ); - }; - - std::tuple<int, int, int> result = lua["f"](100, 200, 300); - // result == { 100, 200, 300 } - - std::tuple<int, int, std::string> result2; - result2 = lua["f"](100, 200, "BARK BARK BARK!"); - // result2 == { 100, 200, "BARK BARK BARK!" } - - int a, int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); - // a == 100 - // b == 200 - // c == "bark" - - -C++ classes from C++ --------------------- - -Everything that is not a: - - * primitive type: ``bool``, ``char/short/int/long/long long``, ``float/double`` - * string type: ``std::string``, ``const char*`` - * function type: function pointers, ``lua_CFunction``, ``std::function``, :doc:`sol::function/sol::protected_function<../api/function>`, :doc:`sol::coroutine<../api/coroutine>`, member variable, member function - * designated sol type: :doc:`sol::table<../api/table>`, :doc:`sol::thread<../api/thread>`, :doc:`sol::error<../api/error>`, :doc:`sol::object<../api/object>` - * transparent argument type: :doc:`sol::variadic_arg<../api/variadic_args>`, :doc:`sol::this_state<../api/this_state>` - * usertype<T> class: :doc:`sol::usertype<../api/usertype>` - -Is set as a :doc:`userdata + usertype<../api/usertype>`. - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - Doge dog{}; - - // Copy into lua: destroyed by Lua VM during garbage collection - lua["dog"] = dog; - // OR: move semantics - will call move constructor if present instead - // Again, owned by Lua - lua["dog"] = std::move( dog ); - lua["dog"] = Doge{}; - lua["dog"] = std::make_unique<Doge>(); - lua["dog"] = std::make_shared<Doge>(); - // Identical to above - - Doge dog2{}; - - lua.set("dog", dog2); - lua.set("dog", std::move(dog2)); - lua.set("dog", Doge{}); - lua.set("dog", std::unique_ptr<Doge>(new Doge())); - lua.set("dog", std::shared_ptr<Doge>(new Doge())); - -``std::unique_ptr``/``std::shared_ptr``'s reference counts / deleters will :doc:`be respected<../api/unique_usertype_traits>`. If you want it to refer to something, whose memory you know won't die in C++, do the following: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge dog{}; // Kept alive somehow - - // Later... - // The following stores a reference, and does not copy/move - // lifetime is same as dog in C++ - // (access after it is destroyed is bad) - lua["dog"] = &dog; - // Same as above: respects std::reference_wrapper - lua["dog"] = std::ref(dog); - // These two are identical to above - lua.set( "dog", &dog ); - lua.set( "dog", std::ref( dog ) ); - -Get userdata in the same way as everything else: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge& dog = lua["dog"]; // References Lua memory - Doge* dog_pointer = lua["dog"]; // References Lua memory - Doge dog_copy = lua["dog"]; // Copies, will not affect lua - -Note that you can change the data of usertype variables and it will affect things in lua if you get a pointer or a reference from Sol: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge& dog = lua["dog"]; // References Lua memory - Doge* dog_pointer = lua["dog"]; // References Lua memory - Doge dog_copy = lua["dog"]; // Copies, will not affect lua - - dog_copy.tailwag = 525; - // Still 50 - lua.script("assert(dog.tailwag == 50)"); - - dog.tailwag = 100; - // Now 100 - lua.script("assert(dog.tailwag == 100)"); - - -C++ classes put into Lua ------------------------- - -See this :doc:`section here<cxx-in-lua>` and after perhaps see if :doc:`simple usertypes suit your needs<../api/simple_usertype>`. Also check out some `a basic example`_, `special functions`_ and `initializers`_, - - -.. _namespacing: - -namespacing ------------ - -You can emulate namespacing by having a table and giving it the namespace names you want before registering enums or usertypes: - -.. code-block:: cpp - - struct my_class { - int b = 24; - - int f () const { - return 24; - } - - void g () { - ++b; - } - }; - - sol::state lua; - lua.open_libraries(); - - // set up table - sol::table bark = lua.create_named_table("bark"); - - bark.new_usertype<my_class>( "my_class", - "f", &my_class::f, - "g", &my_class::g - ); // the usual - - // 'bark' namespace - lua.script("obj = bark.my_class.new()" ); - lua.script("obj:g()"); - my_class& obj = lua["obj"]; - // obj.b == 25 - - -This technique can be used to register namespace-like functions and classes. It can be as deep as you want. Just make a table and name it appropriately, in either Lua script or using the equivalent Sol code. As long as the table FIRST exists (e.g., make it using a script or with one of Sol's methods or whatever you like), you can put anything you want specifically into that table using :doc:`sol::table's<../api/table>` abstractions. - -advanced --------- - -Some more advanced things you can do/read about: - * :doc:`metatable manipulations<../api/metatable_key>` allow a user to change how indexing, function calls, and other things work on a single type. - * :doc:`ownership semantics<ownership>` are described for how lua deals with (raw) pointers. - * :doc:`stack manipulation<../api/stack>` to safely play with the stack. You can also define customization points for ``stack::get``/``stack::check``/``stack::push`` for your type. - * :doc:`make_reference/make_object convenience function<../api/make_reference>` to get the same benefits and conveniences as the low-level stack API but put into objects you can specify. - * :doc:`stack references<../api/stack_reference>` to have zero-overhead Sol abstractions while not copying to the Lua registry. - * :doc:`unique usertype traits<../api/unique_usertype_traits>` allows you to specialize handle/RAII types from other frameworks, like boost, and Unreal, to work with Sol. - * :doc:`variadic arguments<../api/variadic_args>` in functions with ``sol::variadic_args``. - * :doc:`this_state<../api/this_state>` to get the current ``lua_State*``. - * :doc:`resolve<../api/resolve>` overloads in case you have overloaded functions; a cleaner casting utility. - -.. _a basic example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype.cpp -.. _special functions: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_special_functions.cpp -.. _initializers: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_initializers.cpp - |