summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/sol2/docs/source/tutorial/all-the-things.rst')
-rw-r--r--3rdparty/sol2/docs/source/tutorial/all-the-things.rst606
1 files changed, 606 insertions, 0 deletions
diff --git a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
new file mode 100644
index 00000000000..fa9e73ac6c0
--- /dev/null
+++ b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst
@@ -0,0 +1,606 @@
+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
+
+ // 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
+
+
+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["value"]["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<int>( 322 );
+ // first_try == 250
+
+ lua.set("exists", sol::nil);
+
+ int second_try = lua.get_or<int>( 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 will_not_error2 = lua["abc"]["def"]["ghi"]["jklm"].get_or<int>(25);
+ // is 25
+
+ // if you don't go safe,
+ // will throw (or do at_panic if no exceptions)
+ int aaaahhh = lua["abc"]["hope_u_liek_crash"];
+
+
+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
+