2016-04-24 05:16:56 +08:00
tutorial: quick 'n' dirty
=========================
2016-04-24 05:07:51 +08:00
2016-04-24 06:24:48 +08:00
These are all the things. Use your browser's search to find things you want.
2016-04-24 05:07:51 +08:00
2017-09-08 00:22:30 +08:00
.. note ::
2018-01-20 04:03:22 +08:00
After you learn the basics of sol, it is usually advised that if you think something can work, you should TRY IT. It will probably work!
2017-09-08 00:22:30 +08:00
2017-11-10 06:41:46 +08:00
.. note ::
All of the code below is available at the `sol2 tutorial examples`_ .
2018-01-20 04:03:22 +08:00
asserts / prerequisites
-----------------------
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. However, **Lua must be compiled and available** . See the :doc: `getting started tutorial<getting-started>` for more details.
The implementation for `` assert.hpp `` with `` c_assert `` looks like so:
.. literalinclude :: ../../../examples/assert.hpp
:linenos:
This is the assert used in the quick code below.
2016-04-24 05:07:51 +08:00
opening a state
---------------
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/opening_a_state.cpp
:linenos:
2016-04-24 05:07:51 +08:00
2017-11-10 06:41:46 +08:00
.. _sol-state-on-lua-state:
2018-01-20 04:03:22 +08:00
using sol2 on a lua_State\*
---------------------------
2016-04-24 05:07:51 +08:00
2017-11-10 06:41:46 +08:00
For your system/game that already has Lua or uses an in-house or pre-rolled Lua system (LuaBridge, kaguya, Luwra, etc.), but you'd still like sol2 and nice things:
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp
:linenos:
2017-04-01 05:38:04 +08:00
2018-01-20 04:03:22 +08:00
.. _running-lua-code:
2017-04-01 05:38:04 +08:00
2017-11-10 06:41:46 +08:00
running lua code
----------------
2017-04-01 05:38:04 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/running_lua_code.cpp
:linenos:
:lines: 1-10, 16-26
2016-04-24 05:07:51 +08:00
2017-11-10 06:41:46 +08:00
To run Lua code but have an error handler in case things go wrong:
2016-11-05 07:41:16 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/running_lua_code.cpp
:linenos:
2018-01-20 04:03:22 +08:00
:lines: 28-40
running lua code (low-level)
----------------------------
2016-11-05 07:41:16 +08:00
2018-01-20 04:03:22 +08:00
You can use the individual load and function call operator to load, check, and then subsequently run and check code.
.. warning ::
This is ONLY if you need some sort of fine-grained control: for 99% of cases, :ref: `running lua code<running-lua-code>` is preferred and avoids pitfalls in not understanding the difference between script/load and needing to run a chunk after loading it.
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/running_lua_code_low_level.cpp
:linenos:
:lines: 1-10, 16-41
2016-11-05 07:41:16 +08:00
2016-04-24 09:20:45 +08:00
set and get variables
---------------------
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
You can set/get everything using table-like syntax.
2017-07-01 23:02:15 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables.cpp
:linenos:
:lines: 1-19
2016-04-26 03:58:13 +08:00
2017-11-30 02:34:54 +08:00
Equivalent to loading lua values like so:
2016-04-26 03:58:13 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables.cpp
:linenos:
:lines: 22-34
2016-04-26 03:58:13 +08:00
2017-11-30 02:34:54 +08:00
You can show they are equivalent:
2016-04-26 03:58:13 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables.cpp
:linenos:
:lines: 36-44
2016-04-26 03:58:13 +08:00
Retrieve these variables using this syntax:
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables.cpp
:linenos:
:lines: 45-64
2016-04-24 05:07:51 +08:00
2016-04-24 09:20:45 +08:00
Retrieve Lua types using `` object `` and other `` sol:: `` types.
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables.cpp
:linenos:
:lines: 66-
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
You can erase things by setting it to `` nullptr `` or `` sol::lua_nil `` .
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/set_and_get_variables_exists.cpp
:linenos:
2016-04-24 05:07:51 +08:00
2017-11-30 02:34:54 +08:00
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::lua_nil `` , you're probably committing a mistake.
2016-06-28 00:15:32 +08:00
2016-04-24 05:07:51 +08:00
tables
------
2018-01-20 04:03:22 +08:00
Tables can be manipulated using accessor-syntax. Note that :doc: `sol::state<../api/state>` is a table and all the methods shown here work with `` sol::state `` , too.
2016-04-24 05:07:51 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/tables_and_nesting.cpp
:linenos:
:lines: 1-34
2016-04-24 06:24:48 +08:00
2018-01-20 04:03:22 +08:00
If you're going deep, be safe:
2016-04-24 05:07:51 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/tables_and_nesting.cpp
:linenos:
:lines: 35-
2016-04-24 05:07:51 +08:00
make tables
-----------
2018-01-20 04:03:22 +08:00
There are many ways to make a table. Here's an easy way for simple ones:
2016-04-24 05:07:51 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/make_tables.cpp
:linenos:
:lines: 1-21
2016-04-24 05:07:51 +08:00
2018-01-20 04:03:22 +08:00
Equivalent Lua code, and check that they're equivalent:
2016-04-24 05:07:51 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/make_tables.cpp
:linenos:
:lines: 22-
2016-04-24 05:07:51 +08:00
2016-04-24 22:09:05 +08:00
You can put anything you want in tables as values or keys, including strings, numbers, functions, other tables.
2016-09-23 15:35:42 +08:00
Note that this idea that things can be nested is important and will help later when you get into :ref: `namespacing<namespacing>` .
2016-09-09 19:48:28 +08:00
2016-04-24 22:09:05 +08:00
functions
---------
2018-01-20 04:03:22 +08:00
They're easy to use, from Lua and from C++:
2016-04-24 22:09:05 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/functions_easy.cpp
:linenos:
:lines: 1-
2016-04-24 22:09:05 +08:00
2018-01-20 04:03:22 +08:00
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>` .
2016-04-25 10:45:52 +08:00
2016-04-26 03:58:13 +08:00
You can bind member variables as functions too, as well as all KINDS of function-like things:
2016-04-24 22:09:05 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/functions_all.cpp
:linenos:
:lines: 1-50
2016-04-24 22:09:05 +08:00
2016-04-26 03:58:13 +08:00
The lua code to call these things is:
2016-04-24 22:09:05 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/functions_all.cpp
:linenos:
:lines: 51-
2016-04-24 22:09:05 +08:00
2018-01-20 04:03:22 +08:00
You can use `` sol::readonly( &some_class::variable ) `` to make a variable readonly and error if someone tries to write to it.
2016-04-24 22:09:05 +08:00
2016-09-18 10:15:46 +08:00
self call
---------
2018-01-20 04:03:22 +08:00
You can pass the `` self `` argument through C++ to emulate 'member function' calls in Lua.
2016-09-18 10:15:46 +08:00
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/self_call.cpp
:linenos:
:lines: 1-
2016-09-18 10:15:46 +08:00
2016-04-25 00:40:35 +08:00
multiple returns from lua
-------------------------
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/multiple_returns_from_lua.cpp
:linenos:
:lines: 1-
2016-04-25 00:40:35 +08:00
multiple returns to lua
-----------------------
2018-01-20 04:03:22 +08:00
.. literalinclude :: ../../../examples/tutorials/quick_n_dirty/multiple_returns_to_lua.cpp
:linenos:
:lines: 1-
2016-04-25 00:40:35 +08:00
2016-04-26 03:58:13 +08:00
C++ classes from C++
--------------------
2016-04-24 05:07:51 +08:00
Everything that is not a:
* primitive type: `` bool `` , `` char/short/int/long/long long `` , `` float/double ``
* string type: `` std::string `` , `` const char* ``
2016-04-24 22:09:05 +08:00
* 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
2016-04-24 05:07:51 +08:00
* designated sol type: :doc: `sol::table<../api/table>` , :doc: `sol::thread<../api/thread>` , :doc: `sol::error<../api/error>` , :doc: `sol::object<../api/object>`
2017-11-10 06:41:46 +08:00
* transparent argument type: :doc: `sol::variadic_arg<../api/variadic_args>` , :doc: `sol::this_state<../api/this_state>` , :doc: `sol::this_environment<../api/this_environment>`
2016-04-24 05:07:51 +08:00
* usertype<T> class: :doc: `sol::usertype<../api/usertype>`
2016-04-24 22:09:05 +08:00
Is set as a :doc: `userdata + usertype<../api/usertype>` .
2016-04-24 05:07:51 +08:00
.. code-block :: cpp
2016-04-24 22:09:05 +08:00
struct Doge {
int tailwag = 50;
2016-11-17 15:14:29 +08:00
};
2016-04-24 05:07:51 +08:00
Doge dog{};
2016-04-24 22:09:05 +08:00
// Copy into lua: destroyed by Lua VM during garbage collection
2016-04-24 05:07:51 +08:00
lua["dog"] = dog;
// OR: move semantics - will call move constructor if present instead
2016-04-24 22:09:05 +08:00
// Again, owned by Lua
2016-04-24 05:07:51 +08:00
lua["dog"] = std::move( dog );
lua["dog"] = Doge{};
lua["dog"] = std::make_unique<Doge>();
lua["dog"] = std::make_shared<Doge>();
// Identical to above
2016-04-25 10:45:52 +08:00
Doge dog2{};
lua.set("dog", dog2);
lua.set("dog", std::move(dog2));
2016-04-24 05:07:51 +08:00
lua.set("dog", Doge{});
lua.set("dog", std::unique_ptr<Doge>(new Doge()));
lua.set("dog", std::shared_ptr<Doge>(new Doge()));
2016-04-24 22:09:05 +08:00
`` 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:
2016-04-24 05:07:51 +08:00
.. code-block :: cpp
2016-04-24 22:09:05 +08:00
struct Doge {
int tailwag = 50;
2016-11-17 15:14:29 +08:00
};
2016-04-24 22:09:05 +08:00
sol::state lua;
lua.open_libraries(sol::lib::base);
2016-04-24 05:07:51 +08:00
Doge dog{}; // Kept alive somehow
// Later...
// The following stores a reference, and does not copy/move
2016-04-24 06:24:48 +08:00
// lifetime is same as dog in C++
// (access after it is destroyed is bad)
2016-04-24 05:07:51 +08:00
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
2016-04-24 22:09:05 +08:00
struct Doge {
int tailwag = 50;
2016-11-17 15:14:29 +08:00
};
2016-04-24 22:09:05 +08:00
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;
2016-11-17 15:14:29 +08:00
};
2016-04-24 22:09:05 +08:00
sol::state lua;
lua.open_libraries(sol::lib::base);
2016-04-24 05:07:51 +08:00
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)");
2016-04-26 03:58:13 +08:00
C++ classes put into Lua
------------------------
2016-04-25 00:40:35 +08:00
2016-09-22 19:13:04 +08:00
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`_ ,
2016-04-25 00:49:27 +08:00
2016-09-23 15:35:42 +08:00
.. _namespacing:
2016-09-09 19:48:28 +08:00
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
2017-09-25 04:36:45 +08:00
// can add functions, as well (just like the global table)
bark.set_function("print_my_class", [](my_class& self) { std::cout << "my_class { b: " << self.b << " }" << std::endl; });
2016-09-09 19:48:28 +08:00
// 'bark' namespace
lua.script("obj = bark.my_class.new()" );
lua.script("obj:g()");
2017-09-25 04:36:45 +08:00
// access the function on the 'namespace'
lua.script("bark.print_my_class(obj)");
2016-09-09 19:48:28 +08:00
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.
2017-09-08 00:22:30 +08:00
there is a LOT more
-------------------
Some more things you can do/read about:
* :doc: `the usertypes page<../usertypes>` lists the huge amount of features for functions
- :doc: `unique usertype traits<../api/unique_usertype_traits>` allows you to specialize handle/RAII types from other libraries frameworks, like boost and Unreal, to work with Sol. Allows custom smart pointers, custom handles and others
* :doc: `the containers page<../containers>` gives full information about handling everything about container-like usertypes
2017-09-13 07:15:23 +08:00
* :doc: `the functions page<../functions>` lists a myriad of features for functions
2017-09-08 00:22:30 +08:00
- :doc: `variadic arguments<../api/variadic_args>` in functions with `` sol::variadic_args `` .
- also comes with :doc: `variadic_results<../api/variadic_results>` for returning multiple differently-typed arguments
- :doc: `this_state<../api/this_state>` to get the current `` lua_State* `` , alongside other transparent argument types
2016-06-17 22:44:55 +08:00
* :doc: `metatable manipulations<../api/metatable_key>` allow a user to change how indexing, function calls, and other things work on a single type.
2017-03-23 10:34:24 +08:00
* :doc: `ownership semantics<ownership>` are described for how Lua deals with its own internal references and (raw) pointers.
2016-04-24 05:07:51 +08:00
* :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.
2016-06-20 21:51:26 +08:00
* :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.
2016-04-25 00:40:35 +08:00
* :doc: `stack references<../api/stack_reference>` to have zero-overhead Sol abstractions while not copying to the Lua registry.
2017-02-19 04:54:27 +08:00
* :doc: `resolve<../api/resolve>` overloads in case you have overloaded functions; a cleaner casting utility. You must use this to emulate default parameters.
2016-09-22 19:13:04 +08:00
.. _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
2017-11-10 06:41:46 +08:00
.. _sol2 tutorial examples: https://github.com/ThePhD/sol2/tree/develop/examples/tutorials/quick 'n' dirty