diff --git a/docs/source/api/top.rst b/docs/source/api/api-top.rst similarity index 100% rename from docs/source/api/top.rst rename to docs/source/api/api-top.rst diff --git a/docs/source/api/coroutine.rst b/docs/source/api/coroutine.rst index 63edb05f..3d03da31 100644 --- a/docs/source/api/coroutine.rst +++ b/docs/source/api/coroutine.rst @@ -61,6 +61,13 @@ The following are the members of ``sol::coroutine``: members ------- +.. code-block:: cpp + :caption: function: constructor + + coroutine(lua_State* L, int index = -1); + +Grabs the coroutine at the specified index given a ``lua_State*``. + .. code-block:: cpp :caption: returning the coroutine's status :name: status diff --git a/docs/source/api/function.rst b/docs/source/api/function.rst index 22386e0c..a1472f59 100644 --- a/docs/source/api/function.rst +++ b/docs/source/api/function.rst @@ -7,7 +7,15 @@ calling functions bound to Lua class function : public reference; -Function is a correct-assuming version of :doc:`protected_function`, omitting the need for typechecks and error handling. It is the default function type of Sol. When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :ref:`function_result` class that gets implicitly converted to the requested return type. For example: +Function is a correct-assuming version of :doc:`protected_function`, omitting the need for typechecks and error handling. It is the default function type of Sol. Grab a function directly off the stack using the constructor: + +.. code-block:: cpp + :caption: constructor: function + + function(lua_State* L, int index = -1); + + +When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :ref:`function_result` class that gets implicitly converted to the requested return type. For example: .. code-block:: lua :caption: func_barks.lua diff --git a/docs/source/api/object.rst b/docs/source/api/object.rst index 5817aa59..bdcc829e 100644 --- a/docs/source/api/object.rst +++ b/docs/source/api/object.rst @@ -14,6 +14,13 @@ general-purpose safety reference to an existing object members ------- +.. code-block:: cpp + :caption: constructor: coroutine + + coroutine(lua_State* L, int index = -1); + +Create an object which references the specific element at the given index in the specified ``lua_State*``. + .. code-block:: cpp :caption: function: type conversion diff --git a/docs/source/api/protected_function.rst b/docs/source/api/protected_function.rst index 0b55d292..76b4d7c3 100644 --- a/docs/source/api/protected_function.rst +++ b/docs/source/api/protected_function.rst @@ -7,7 +7,15 @@ Lua function calls that trap errors and provide error handler class protected_function : public reference; -Inspired by a request from `starwing` in the old repository, this class provides the same interface as :doc:`function` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :doc:`protected_function_result` class that gets implicitly converted to the requested return type. For example: +Inspired by a request from `starwing` in the old repository, this class provides the same interface as :doc:`function` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. Grab a function directly off the stack using the constructor: + +.. code-block:: cpp + :caption: constructor: protected_function + + protected_function(lua_State* L, int index = -1); + + +When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :doc:`protected_function_result` class that gets implicitly converted to the requested return type. For example: .. code-block:: lua :caption: pfunc_barks.lua diff --git a/docs/source/api/reference.rst b/docs/source/api/reference.rst index 5ba34eab..9c0c247f 100644 --- a/docs/source/api/reference.rst +++ b/docs/source/api/reference.rst @@ -14,6 +14,13 @@ This type keeps around a reference to something that was on the stack and places members ------- +.. code-block:: cpp + :caption: constructor: reference + + reference(lua_State* L, int index = -1); + +Creates a reference from the Lua stack at the specified index, saving it into the metatable registry. This constructor is exposed on all types that derive from ``sol::reference``. + .. code-block:: cpp :caption: function: push referred-to element from the stack diff --git a/docs/source/api/stack.rst b/docs/source/api/stack.rst index c192e572..9296448e 100644 --- a/docs/source/api/stack.rst +++ b/docs/source/api/stack.rst @@ -7,7 +7,7 @@ the nitty-gritty core abstraction layer over Lua namespace stack -If you find that the higher level abstractions are not meeting your needs, you may want to delve into the ``stack`` namespace to try and get more out of Sol. ``stack.hpp`` and the ``stack`` namespace define several utilities to work with Lua, including pushing / popping utilities, getters, type checkers, Lua call helpers and more. This namespace is not thoroughly documented as the majority of its interface is mercurial and subject to change between releases to either heavily boost performance or improve the Sol :doc:`api`. +If you find that the higher level abstractions are not meeting your needs, you may want to delve into the ``stack`` namespace to try and get more out of Sol. ``stack.hpp`` and the ``stack`` namespace define several utilities to work with Lua, including pushing / popping utilities, getters, type checkers, Lua call helpers and more. This namespace is not thoroughly documented as the majority of its interface is mercurial and subject to change between releases to either heavily boost performance or improve the Sol :doc:`api`. There are, however, a few :ref:`template customization points` that you may use for your purposes and a handful of potentially handy functions. These may help if you're trying to slim down the code you have to write, or if you want to make your types behave differently throughout the Sol stack. Note that overriding the defaults **can** throw out many of the safety guarantees Sol provides: therefore, modify the :ref:`extension points` at your own discretion. diff --git a/docs/source/api/table.rst b/docs/source/api/table.rst index fec3ce42..502cb9ca 100644 --- a/docs/source/api/table.rst +++ b/docs/source/api/table.rst @@ -21,6 +21,13 @@ Tables are the core of Lua, and they are very much the core of Sol. members ------- +.. code-block:: cpp + :caption: constructor: table + + table(lua_State* L, int index = -1); + +Takes a table from the Lua stack at the specified index and allows a person to use all of the abstractions therein. + .. code-block:: cpp :caption: function: get / traversing get @@ -30,6 +37,9 @@ members template decltype(auto) traverse_get(Keys&&... keys) const; + template + decltype(auto) get_or(Key&& key, T&& otherwise) const; + template decltype(auto) get_or(Key&& key, D&& otherwise) const; diff --git a/docs/source/api/thread.rst b/docs/source/api/thread.rst index 40104472..1a713f97 100644 --- a/docs/source/api/thread.rst +++ b/docs/source/api/thread.rst @@ -12,6 +12,13 @@ a separate state that can contain and run functions members ------- +.. code-block:: cpp + :caption: constructor: thread + + thread(lua_State* L, int index = -1); + +Takes a thread from the Lua stack at the specified index and allows a person to use all of the abstractions therein. + .. code-block:: cpp :caption: function: view into thread_state()'s state diff --git a/docs/source/features.rst b/docs/source/features.rst index 6e69fe10..449edb21 100644 --- a/docs/source/features.rst +++ b/docs/source/features.rst @@ -52,59 +52,86 @@ The Feature Matrix™ The below feature table checks for the presence of something. It, however, does not actually account for any kind of laborious syntax. -✔ full support +✔ full support: works as you'd expecte (operator[] on tables, etc...) -~ partial support / wonky support +~ partial support / wonky support: this means its either supported through some other fashion (not with the desired syntax, serious caveats, etc.). Sometimes means dropping down t use the plain C API. -✗ no support +✗ no support: feature doesn't work or, if it's there, it REALLY sucks to use + +Implementation notes from using the libraries are below the tables. -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| | plain C | luawrapper | lua-intf | luabind | Selene | Sol | oolua | lua-api-pp | kaguya | -| | | | | | | | | | | -+===========================+=============+============+==========+=========+==========+===========+===========+================+==========+ -| tables | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| table chaining | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| arbitrary keys | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| user-defined types (udts) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| udts: member functions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| udts: variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| stack abstractions | ~ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| protected function | ✔ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| multi-return | ~ | ✗ | ✗ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| inheritance | ~ | ✗ | ✗ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| thread | ✔ | ✗ | ✗ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| coroutines | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| no-rtti support | ✔ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| no-exception support | ✔ | ✗ | ~ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| Lua 5.1 | ✔ | ✔ | ~ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| luajit | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ -| distribution | compile | header | both | compile | header | header | compile | compile | header | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+ +category explanations +--------------------- + +Explanations for a few categories are below (rest are self-explanatory). + +* optional: Support for getting an element, or potentially not (and not forcing the default construction of what amounts to a bogus/dead object). Usually comes with ``std(::experimental)::optional``. It's a fairly new class, so a hand-rolled class internal to the framework with similar semantics is also acceptable +* tables: Some sort of abstraction for dealing with tables. Ideal support is ``mytable["some_key"] = value``, and everything that the syntax implies. +* table chaining: In conjunction with tables, having the ability to do nest deeply into tables ``mytable["key1"]["key2"]["key3"]``. Note that this becomes a tripping point for some libraries: crashing if ``"key1"`` doesn't exist while trying to access ``"key2"`` (Sol avoids this specifically when you use ``sol::optional``), and sometimes it's also a heavy performance bottleneck as expressions are not lazy-evaluated by a library. +* arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table without dropping to the plain API. +* user-defined types (udts): C++ types given form and function in lua code. +* udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua. +* udts - variables: C++ member variables, manipulated by ``my_object.var = 24`` and friends +* function bindind: +* protected function: +* multi-return: returning multiple values from and to lua +* inheritance: allowing some degree of subtyping or inheritance on classes / userdata from lua +* overloading: the ability to call overloaded functions, matched based on arity or type (``foo( 1 )`` from lua calls a different function then ``foo( "bark" )``). +* lua thread: basic wrapping of the lua thread API; ties in with coroutine. +* coroutines: allowing a function to be called multiple times, + ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| | plain C | luawrapper | lua-intf | luabind | Selene | Sol | oolua | lua-api-pp | kaguya | SLB | SWIG | luacppinterface | +| | | | | | | | | | | | | | ++===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+ +| optional | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| tables | ~ | ~ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✗ | ✗ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| table chaining | ~ | ~ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✗ | ✗ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| arbitrary keys | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ~ | ✔ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| user-defined types (udts) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| udts: member functions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| udts: variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | ✗ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| stack abstractions | ~ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✗ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| lua function from C(++) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| protected function | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| multi-return | ~ | ✗ | ✗ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| inheritance | ~ | ✗ | ✗ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ✔ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| lua thread | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| coroutines | ~ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| no-rtti support | ✔ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| no-exception support | ✔ | ✗ | ~ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| Lua 5.1 | ✔ | ✔ | ~ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ +| distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+ + notes on implementations ------------------------ @@ -113,53 +140,7 @@ Plain C - * Obviously you can do anything you want with Plain C, but the effort involved is astronomical in comparison to what frameworks offer * Does not scale very well (in terms of developer ease of use) -* Compilation (or package manager use) is obviously required for your platform and required to use ANY of these libraries whatsoever - -luawrapper - - -* Takes the approach of writing and reading tables using ``readVariable`` and ``writeVariable`` functions -* C++11 -* No macros -* The interface can be clunky (no table-like data structures: most things go though ``readVariable`` / ``writeVariable``) - - -lua-intf - - -* Can be both header-only or compiled -* C++11 -* Macro-based registration (strange pseudo-language) -* Fairly fast in most regards -* Registering classes/"modules" in using C++ code is extremely verbose - -luabind - - -* One of the older frameworks, but has many people updating it and providing "deboostified" versions -* Strange in-lua keywords and parsing to allow for classes to be written in lua - - not sure if good feature; vendor lock-in to that library to depend on this specific class syntax? - -Selene - - -* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get -* Registering classes/"modules" using C++ code is extremely verbose - -Sol - - -* Overloading support can get messy with inheritance, see :doc:`here` -* Only (?) library that supports table-like use of variables as shown in the :doc:`sneak peek` -* C++14/"C++1y" (-std=c++14, -std=c++1y, =std=c++1z) flags are used (available since GCC 4.9 and Clang 3.5) - -oolua - - -* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs.`_ -* Supports not having exceptions or rtti turned on (shiny!) - -.. _ fn1: - -lua-api-pp - - -* Compiled, but the recommendation is to add the source files directly to your project -* Userdata registration with nice, thick macros: LUAPP_USERDATA( ... ) plus a bunch of free functions that take a ``T& self`` argument -* C++11-ish in some regards +* Compilation (or package manager use) is obviously required for your platform and required to use ANY of these libraries, but that's okay because all libraries need some version of Lua anyways, so you always have this! kaguya - @@ -167,10 +148,93 @@ kaguya - * Inspired coroutine support for Sol * Library author (satoren) is a nice guy! * C++11/14, or boostified (which makes it C++03 compatible) +* Clas registration is a bit verbose, but not as offensive as OOLua or lua-intf or others +* Deserves lots of love! -TODO: -* SWIG - http://www.swig.org/Doc1.3/Lua.html#Lua_nn2 -* SLB3 - https://code.google.com/archive/p/slb/ +Sol - + +* Only library with Optional support, hoorah! +* Prrreeettty fast (still working on being the ABSOLUTE FASTEST)! +* Overloading support can get messy with inheritance, see :doc:`here` +* C++14/"C++1y" (-std=c++14, -std=c++1y, =std=c++1z) flags are used (available since GCC 4.9 and Clang 3.5) +* Active issues, active individuals +* Deserves lots of love! + +lua-intf - + +* Can be both header-only or compiled +* C++11 +* Macro-based registration (strange pseudo-language) +* Fairly fast in most regards +* Registering classes/"modules" in using C++ code is extremely verbose +* Not too shabby! + +Selene - + +* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get +* Registering classes/"modules" using C++ code is extremely verbose, similar to lua-intf's style +* Eats crap when it comes to performance, most of the time (see :doc:`benchmarks`) +* Lots of users, but the Repository is kinda stagnant... -.. _Go read the docs.: https://oolua.org/docs/index.html \ No newline at end of file +luawrapper - + +* Takes the approach of writing and reading tables using ``readVariable`` and ``writeVariable`` functions +* C++11 +* No macros! +* The interface can be clunky (no table-like data structures: most things go though ``readVariable`` / ``writeVariable``) + +SWIG (3.0) - + +* Very comprehensive for binding concepts of C++ (classes, variables, etc.) to lua +* Helps with literally nothing else (tables, threads, stack abstractions, etc.) +* Not really a good, full-featured Library... +* Requires preprocessing step (but it's not a... TERRIBLY complicated preprocessing step); some boilerplate in writing additional classes that you've already declared + +luacppinterface - + +* It seems like a decent library, until you try to get a function put into Lua using CreateFunction, and then getting it out again -- it fails miserably +* No member variable support +* Actually has tables (but no operator[]) +* Does not support arbitrary keys +* Really has potential, but falls down on its face... + +luabind - + +* One of the older frameworks, but has many people updating it and providing "deboostified" versions +* Strange in-lua keywords and parsing to allow for classes to be written in lua + - not sure if good feature; vendor lock-in to that library to depend on this specific class syntax? + +lua-api-pp - + +* Compiled, but the recommendation is to add the source files directly to your project +* Userdata registration with thick setup-macros: LUAPP_USERDATA( ... ) plus a bunch of free functions that take a ``T& self`` argument + - You can still bind member functions straight away in some cases, however +* You have to create a context and then call it to start accessing the lua state (adding more boilerplate... thanks) + - Thankfully, unlike many libraries, it actually has a Table type that can be used semi-easily. FINALLY. +* C++11-ish in some regards + +SLB3 - + +* Old code exported to github from dying google code +* ".NET Style" - to override functionality, derive from class -- boilerplate (isn't that what we're trying to get rid of?) +* Pointers everywhere: ownership semantics unclear +* Piss-poor documentation, ugh! +* Least favorite to work with, for sure! + +oolua - + +* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs`_ +* The worst in terms of how to use it: may have docs, but the DSL (despite using C++11) is extraordinarily crappy with thick, hard-to-debug/hard-to-error-check macros (and seems not to compile on VS 2015 Update 2 properly for Userdata bindings?) +* Supports not having exceptions or rtti turned on (shiny!) +* Poor RAII support: default-construct-and-get style (requires some form of initalization to perform a ``get`` of an object, and it's hard to extend) + +luwra - + +* Mentioned here because... well, it's a thing +* Lightweight (read: feature-starved) wrapper library +* Can push/pop to the global namespace, but doing anymore more detailed is... harder +* Might as well go with luawrapper if you're going to bother + + +.. _Go read the docs: https://oolua.org/docs/index.html \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 4aaaa3eb..897c28c3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -18,22 +18,23 @@ get going: ---------- .. toctree:: - :maxdepth: 1 - :name: mastertoc + :maxdepth: 1 + :name: mastertoc - api/top - features - benchmarks - safety - exceptions - rtti - licenses - origin + tutorial/tutorial-top + api/api-top + features + benchmarks + safety + exceptions + rtti + licenses + origin "I need feature X, maybe you have it?" -------------------------------------- -Take a look at the :doc:`Features` page: it links to much of the API. You can also just straight up browse the API. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker. +Take a look at the :doc:`Features` page: it links to much of the API. You can also just straight up browse the :doc:`api` or ease in with the :doc:`tutorials`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker. the basics: diff --git a/docs/source/tutorial/cxx-in-lua.rst b/docs/source/tutorial/cxx-in-lua.rst new file mode 100644 index 00000000..7a950c6e --- /dev/null +++ b/docs/source/tutorial/cxx-in-lua.rst @@ -0,0 +1,4 @@ +C++ in Lua +========== + +Using user defined types ("usertype"s, or just "udt"s) is simple with Sol. If you don't call any member variables or functions, then you don't even have to 'register' the usertype at all: just pass it through. \ No newline at end of file diff --git a/docs/source/tutorial/existing.rst b/docs/source/tutorial/existing.rst index d9afdfeb..35d15a56 100644 --- a/docs/source/tutorial/existing.rst +++ b/docs/source/tutorial/existing.rst @@ -12,7 +12,12 @@ If you're already using lua and you just want to use ``sol`` in some places, you // start using Sol with a pre-existing system sol::state_view lua(L); // non-owning - lua.script("print('bark bark bark!')") + lua.script("print('bark bark bark!')"); + + sol::table expected_table(L); // get the table off the top of the stack + // start using it... } -Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. \ No newline at end of file +Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. After you do that, all of the power of `Sol` is available to you, and then some! + +Remember that Sol can be as lightweight as you want it: almost all of Sol's types take the ``lua_State*`` argument and then a second ``int index`` stack index argument, meaning you can use :doc:`tables<../api/table>`, :doc:`lua functions<../api/function>`, :doc:`tables<../api/table>`, and other reference-derived objects that expose the proper constructor for your use. \ No newline at end of file diff --git a/docs/source/tutorial/functions.rst b/docs/source/tutorial/functions.rst new file mode 100644 index 00000000..196232ae --- /dev/null +++ b/docs/source/tutorial/functions.rst @@ -0,0 +1,4 @@ +functions and You +================= + +Sol can register all kinds of functions. \ No newline at end of file diff --git a/docs/source/tutorial/getting-started.rst b/docs/source/tutorial/getting-started.rst index 580a7b1a..4dcd2961 100644 --- a/docs/source/tutorial/getting-started.rst +++ b/docs/source/tutorial/getting-started.rst @@ -3,14 +3,20 @@ getting started Let's get you going with Sol! To start, you'll need to use a lua distribution of some sort. Sol doesn't provide that: it only wraps the API that comes with it, so you can pick whatever distribution you like for your application. There are lots, but the two popular ones are `vanilla Lua`_ and speedy `LuaJIT`_ . We recommend vanilla Lua if you're getting started, LuaJIT if you need speed and can handle some caveats: the interface for Sol doesn't change no matter what Lua version you're using. -When you're ready: try compiling this short snippet: +After that, make sure you grab either the `single header file release`_, or just perform a clone of the `github repository here`_ and set your include paths up so that you can get at ``sol.hpp`` somehow. We recommend the single-header-file release, since it's easier to move around, manage and update if you commit it with some form of version control. + +.. note:: + + If you get an avalanche of errors (particularly referring to ``auto``), you may not have enabled C++14 / C++17 mode for your compiler. Add one of ``std=c++14``, ``std=c++1z`` OR ``std=c++1y`` to your compiler options. By default, this is always-on for VC++ compilers in Visual Studio and friends, but g++ and clang++ require a flag (unless you're on `GCC 6.0`_). + +When you're ready, try compiling this short snippet: .. code-block:: cpp :linenos: :caption: the first snippet :name: the-first-snippet - #include "sol.hpp" // or #include , whichever suits your needs + #include // or #include "sol.hpp", whichever suits your needs int main (int argc, char* argv[]) { @@ -22,11 +28,19 @@ When you're ready: try compiling this short snippet: return 0; } -If this works, you're ready to start! The first line creates the ``lua_State`` and will hold onto it for the duration of the scope its declared in (e.g., from the opening ``{`` to the closing ``}``). It will automatically close / cleanup that lua state when it gets destructed. The second line opens a single lua-provided library, "base". There are several other libraries that come with lua that you can open by default, and those are included in the :ref:`sol::lib::base` enumeration. +If this works, you're ready to start! The first line creates the ``lua_State`` and will hold onto it for the duration of the scope its declared in (e.g., from the opening ``{`` to the closing ``}``). It will automatically close / cleanup that lua state when it gets destructed. The second line opens a single lua-provided library, "base". There are several other libraries that come with lua that you can open by default, and those are included in the :ref:`sol::lib` enumeration. + +If you're interested in integrating Sol with a project that already uses some other library or Lua in the codebase, check out the :doc:`existing example` to see how to work with Sol when you add it to a project! Next, let's start :doc:`reading/writing some variables` from Lua into C++, and vice-versa! .. _vanilla Lua: https://www.lua.org/ -.. _LuaJIT: http://luajit.org/ \ No newline at end of file +.. _LuaJIT: http://luajit.org/ + +.. _GCC 6.0: https://gcc.gnu.org/gcc-6/changes.html + +.. _single header file release: https://github.com/ThePhD/sol2/releases + +.. _github repository here: https://github.com/ThePhD/sol2 \ No newline at end of file diff --git a/docs/source/tutorial/tutorial-top.rst b/docs/source/tutorial/tutorial-top.rst new file mode 100644 index 00000000..b03475d5 --- /dev/null +++ b/docs/source/tutorial/tutorial-top.rst @@ -0,0 +1,16 @@ +get going FAST +============== + +Ride into the speed lane by learning the all the ins-and-outs of Sol with these tutorials! You'll be up and running in minutes, maybe even faster if you're just That Good™. + + +.. toctree:: + :caption: Sol Tutorial + :name: tutorialtoc + :maxdepth: 1 + + getting-started + existing + variables + functions + cxx-in-lua diff --git a/docs/source/tutorial/variables.rst b/docs/source/tutorial/variables.rst index 04dfb9b9..09ef5c81 100644 --- a/docs/source/tutorial/variables.rst +++ b/docs/source/tutorial/variables.rst @@ -18,6 +18,8 @@ reading :caption: main.cpp :name: variables-main-cpp + #include + int main () { sol::state lua; @@ -32,6 +34,8 @@ You can interact with the variables like this: :caption: main.cpp extended :name: extended-variables-main-cpp + #include + #include #include // for std::pair int main () { @@ -50,13 +54,13 @@ You can interact with the variables like this: // table and state can have multiple things pulled out of it too std::pair xyresolution = resolution.get( "x", "y" ); // As an example, you can also pull out a tuple as well - // std::tuple xyresolution = resolution.get( "x", "y" ); + std::tuple xyresolutiontuple = resolution.get( "x", "y" ); return 0; } -From this example, you can see that there's many ways to pull out the varaibles you want. Some can be more safe than others. For example, to determine if a nested variable exists or not, you can use ``auto`` to capture the value of a ``table[key]`` lookup, and then use the ``.valid()`` method: +From this example, you can see that there's many ways to pull out the varaibles you want. You can get For example, to determine if a nested variable exists or not, you can use ``auto`` to capture the value of a ``table[key]`` lookup, and then use the ``.valid()`` method: .. code-block:: cpp :caption: safe lookup @@ -69,7 +73,7 @@ From this example, you can see that there's many ways to pull out the varaibles // Branch taken: config is a not a variable } -This comes in handy when you want to check if a nested variable exists. You can also check if a toplevel variable is present or not by using ``sol::optional``, which also checks if the type you're trying to get is of a specific type: +This comes in handy when you want to check if a nested variable exists. You can also check if a toplevel variable is present or not by using ``sol::optional``, which also checks if A) the keys you're going into exist and B) the type you're trying to get is of a specific type: .. code-block:: cpp :caption: optional lookup @@ -89,3 +93,89 @@ This comes in handy when you want to check if a nested variable exists. You can // Branch not taken: that variable is not present } +This can come in handy when, even in optimized or release modes, you still want the safety of checking. You can also use the `get_or` methods to, if a certain value may be present but you just want to default the value to something else: + +.. code-block:: cpp + :caption: get_or lookup + + // this will result in a value of '24' + int is_defaulted = lua["config"]["fullscreen"].get_or( 24 ); + + // This will result in the value of the config, which is 'false' + bool is_not_defaulted = lua["config"]["fullscreen"]; + +That's all it takes to read variables! + + +writing +------- + +Writing gets a lot simpler. Even without scripting a file or a string, you can read and write variables into lua as you please: + +.. code-block:: cpp + :caption: main.cpp + :name: writing-main-cpp + + #include + #include + + int main () { + + sol::state lua; + + // open those basic lua libraries again, like print() etc. + lua.open_libs( sol::lib::base ); + + // value in the global table + lua["bark"] = 50; + + // a table being created in the global table + lua["some_table"] = lua.create_table_with( + "key0", 24, + "key1", 25, + lua["bark"], "the key is 50 and this string is its value!" + ); + + // Run a plain ol' string + // Using a "Raw String Literal" to have multi-line goodness: http://en.cppreference.com/w/cpp/language/string_literal + lua.script(R"( + + print(some_table[50]) + print(some_table["key0"]) + print(some_table["key1"]) + + -- a lua comment: access a global in a lua script with the _G table + print(_G["bark"]) + + )"); + + return 0; + } + +This example pretty much sums up what can be done. Note that the syntax ``lua["non_existing_key_1"] = 1`` will make that variable, but if you tunnel too deep without first creating a table, the Lua API will panic (e.g., ``lua["does_not_exist"]["b"] = 20`` will trigger a panic). You can also be lazy with reading / writing values: + +.. code-block:: cpp + :caption: main.cpp + :name: lazy-main-cpp + + #include + #include + + int main () { + + sol::state lua; + + auto barkkey = lua["bark"]; + if (barkkey.valid()) { + // Branch not taken: doesn't exist yet + std::cout << "How did you get in here, arf?!" << std::endl; + } + + barkkey = 50; + if (barkkey.valid()) { + // Branch taken: value exists! + std::cout << "Bark Bjork Wan Wan Wan" << std::endl; + } + } + +It's easy to see that there's a lot of options to do what you want here. But, these are just traditional numbers and strings. What if we want more power, more capabilities than what these limited types can offer us? Let's throw some :doc:`functions in there` :doc:`C++ classes into the mix`! \ No newline at end of file diff --git a/sol/proxy.hpp b/sol/proxy.hpp index 3a9b92bb..c68c5ad7 100644 --- a/sol/proxy.hpp +++ b/sol/proxy.hpp @@ -78,6 +78,25 @@ public: return tuple_get( std::make_index_sequence>::value>() ); } + template + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get()) U; + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + template decltype(auto) operator[](K&& k) const { auto keys = meta::tuplefy(key, std::forward(k)); diff --git a/tests.cpp b/tests.cpp index ea093741..29d51bef 100644 --- a/tests.cpp +++ b/tests.cpp @@ -291,12 +291,10 @@ TEST_CASE("simple/get_or", "check if table.get_or works correctly") { sol::state lua; auto bob_table = lua.create_table("bob"); - int is_set=0; - int is_not_set=0; - bob_table.set("is_set",42); + bob_table.set("is_set", 42); - is_set = bob_table.get_or("is_set", 3); - is_not_set = bob_table.get_or("is_not_set", 22); + int is_set = bob_table.get_or("is_set", 3); + int is_not_set = bob_table.get_or("is_not_set", 22); REQUIRE(is_set == 42); REQUIRE(is_not_set == 22); @@ -306,6 +304,23 @@ TEST_CASE("simple/get_or", "check if table.get_or works correctly") { REQUIRE(bark == 55.6); } +TEST_CASE("simple/proxy_get_or", "check if proxy.get_or works correctly") { + sol::state lua; + + auto bob_table = lua.create_table("bob"); + bob_table.set("is_set", 42); + + int is_set = bob_table["is_set"].get_or( 3 ); + int is_not_set = bob_table[ "is_not_set" ].get_or( 22 ); + + REQUIRE(is_set == 42); + REQUIRE(is_not_set == 22); + + lua["joe"] = 55.6; + double bark = lua["joe"].get_or( 60 ); + REQUIRE(bark == 55.6); +} + TEST_CASE("simple/addition", "check if addition works and can be gotten through lua.get and lua.set") { sol::state lua;