filters -> policies

shill out on the docs
prepare to update all docs
fix #809
This commit is contained in:
ThePhD 2019-05-21 03:57:10 -04:00
parent ad1b9666c1
commit 4808e7cad8
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
44 changed files with 264 additions and 218 deletions

View File

@ -1,4 +1,4 @@
## sol2 (Sol v3.0.0-beta2)
## sol3 (sol2 v3.0.2)
[![Join the chat in Discord: https://discord.gg/buxkYNT](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/buxkYNT)
@ -6,6 +6,8 @@
[![Windows Build status](https://ci.appveyor.com/api/projects/status/n38suofr21e9uk7h?svg=true)](https://ci.appveyor.com/project/ThePhD/sol2)
[![Documentation Status](https://readthedocs.org/projects/sol2/badge/?version=latest)](http://sol2.readthedocs.io/en/latest/?badge=latest)
![Liberapay patrons](https://img.shields.io/liberapay/patrons/ThePhD.svg) ![Patrons](https://shieldsio-patreon.herokuapp.com/ThePhD/pledges) [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/W7W8Q619) [![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/thephd)
Sol is a C++ library binding to Lua. It currently supports all Lua versions 5.1+ (LuaJIT 2.x included). Sol aims to be easy to use and easy to add to a project.
The library is header-only for easy integration with projects.
@ -49,9 +51,7 @@ More examples are given in the examples directory [here](https://github.com/TheP
## Supporting
Help the project grow on [Patreon](https://www.patreon.com/thephd)!
You can also [donate to support Sol](https://www.paypal.me/LMeneide), which is always appreciated! There are reward tiers for patrons on Patreon, too!
Please use the buttons above and help this project grow.
You can also help out the library by submitting pull requests to fix anything or add anything you think would be helpful! This includes making small, useful examples of something you haven't seen, or fixing typos and bad code in the documentation.
@ -86,7 +86,7 @@ CppCon 2018 - 404 Keystone, Meydenbauer Center, Aspen, Colorado
You can grab a single header (and the single forward header) out of the library [here](https://github.com/ThePhD/sol2/tree/develop/single). For stable version, check the releases tab on GitHub for a provided single header file for maximum ease of use. A script called [`single.py`](https://github.com/ThePhD/sol2/blob/develop/single/single.py) is provided in the repository if there's some bleeding edge change that hasn't been published on the releases page. You can run this script to create a single file version of the library so you can only include that part of it. Check `single.py --help` for more info.
If you use CMake, you can also configure and generate a project that will generate the sol2_single_header for you. You can also include the project using CMake. Run CMake for more details. Thanks @Nava2, @alkino, @mrgreywater and others for help with making the CMake build a reality.
If you use CMake, you can also configure and generate a project that will generate the `sol2_single_header` for you. You can also include the project using CMake. Run CMake for more details. Thanks @Nava2, @alkino, @mrgreywater and others for help with making the CMake build a reality.
## Features
@ -122,7 +122,7 @@ Please make sure you use the `-std=c++2a`, `-std=c++1z`, `-std=c++17` or better
If you would like support for an older compiler (at the cost of some features), use the latest tagged sol2 branch. If you would like support for an even older compiler, feel free to contact me for a Custom Solution.
sol2 is checked by-hand for other platforms as well, including Android-based builds with GCC and iOS-based builds out of XCode with Apple-clang. It should work on both of these platforms, so long as you have the proper standards flags.
sol3 is checked by-hand for other platforms as well, including Android-based builds with GCC and iOS-based builds out of XCode with Apple-clang. It should work on both of these platforms, so long as you have the proper standards flags.
## Running the Tests

View File

@ -42,7 +42,7 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
property
var
protect
filters
policies
readonly
as_function
c_call

View File

@ -17,7 +17,7 @@ The goal of ``sol::c_call<...>`` is to provide a way to wrap a function and tran
This can also be placed into the argument list for a :doc:`usertype<usertype>` as well.
This pushes a raw ``lua_CFunction`` into whatever you pass the resulting ``c_call`` function pointer into, whether it be a table or a userdata or whatever else using sol2's API. The resulting ``lua_CFunction`` can also be used directly with the lua API, just like many of sol2's types can be intermingled with Lua's API if you know what you're doing.
This pushes a raw ``lua_CFunction`` into whatever you pass the resulting ``c_call`` function pointer into, whether it be a table or a userdata or whatever else using sol3's API. The resulting ``lua_CFunction`` can also be used directly with the lua API, just like many of sol3's types can be intermingled with Lua's API if you know what you're doing.
It is advisable for the user to consider making a macro to do the necessary ``decltype( &function_name, ), function_name``. Sol does not provide one because many codebases already have `one similar to this`_.

View File

@ -1,26 +1,26 @@
filters
=======
policies
========
*stack modification right before lua call returns*
``sol::filters`` is an advanced, low-level modification feature allowing you to take advantage of sol2's abstractions before applying your own stack-based modifications at the last moment. They cover the same functionality as `luabind's "return reference to" and "dependency"`_ types. A few pre-rolled filters are defined for your use:
``sol::policies`` is an advanced, low-level modification feature allowing you to take advantage of sol3's abstractions before applying your own stack-based modifications at the last moment. They cover the same functionality as `luabind's "return reference to" and "dependency"`_ types. A few pre-rolled policies are defined for your use:
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| filter | usage | modification |
| policy | usage | modification |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``sol::returns_self`` | ``sol::filters( some_function, sol::returns_self() )`` | - takes the argument at stack index 1 (``self`` in member function calls and lambdas that take a specific userdata first) and makes that to be the return value |
| ``sol::returns_self`` | ``sol::policies( some_function, sol::returns_self() )`` | - takes the argument at stack index 1 (``self`` in member function calls and lambdas that take a specific userdata first) and makes that to be the return value |
| | | - rather than creating a new userdata that references the same C++ memory, it copies the userdata, similar to writing ``obj2 = obj1`` just increases the reference count |
| | | - saves memory space on top of keeping original memory alive |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``sol::returns_self_with<int...>`` | ``sol::filters( some_function, sol::returns_self_with<2, 3>() )`` | - same as above, with the caveat that the ``self`` is returned while also putting dependencies into the ``self`` |
| ``sol::returns_self_with<int...>`` | ``sol::policies( some_function, sol::returns_self_with<2, 3>() )`` | - same as above, with the caveat that the ``self`` is returned while also putting dependencies into the ``self`` |
| | | - can keep external dependencies alive |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``sol::self_dependency`` | ``sol::filters( some_function, sol::self_dependency() );`` | - this makes the value returned by the bindable take a dependency on the ``self`` argument |
| ``sol::self_dependency`` | ``sol::policies( some_function, sol::self_dependency() );`` | - this makes the value returned by the bindable take a dependency on the ``self`` argument |
| | | - useful for returning a reference to a member variable and keeping the parent class of that member variable alive |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``sol::stack_dependencies`` | ``sol::filters( some_function, sol::stack_dependencies( target_index, 2, 1, ... ) );`` | - whatever is at ``target_index`` on the stack is given a special "keep alive" table with the elements on the stack specified by the integer indices after ``target_index`` |
| ``sol::stack_dependencies`` | ``sol::policies( some_function, sol::stack_dependencies( target_index, 2, 1, ... ) );`` | - whatever is at ``target_index`` on the stack is given a special "keep alive" table with the elements on the stack specified by the integer indices after ``target_index`` |
| | | - allows you to keep arguments and other things alive for the duration of the existence of the class |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| custom | ``sol::filters( some_function, [](lua_State* L, int current_stack_return_count) -> int { ... } )`` | - whatever you want, so long as it has the form ``int (lua_State*, int )`` |
| custom | ``sol::policies( some_function, [](lua_State* L, int current_stack_return_count) -> int { ... } )``| - whatever you want, so long as it has the form ``int (lua_State*, int )`` |
| | | - works with callables (such as lambdas), so long as it has the correct form |
| | | - expected to return the number of things on the stack to return to Lua |
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@ -30,6 +30,6 @@ filters
| - works with ``table::set( ... )``, ``table::set_function( ... );``, and on all usertype bindings |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
You can specify multiple filters on the same ``sol::filters`` call, and can also specify custom filters as long as the signature is correct.
You can specify multiple policies on the same ``sol::policies`` call, and can also specify custom policies as long as the signature is correct.
.. _luabind's "return reference to" and "dependency": http://www.rasterbar.com/products/luabind/docs.html#dependency

View File

@ -171,5 +171,5 @@ on function objects and proxies
.. note::
As of recent versions of sol2 (2.18.2 and above), this is no longer an issue, as even bound classes will have any detectable function call operator automatically bound to the object, to allow this to work without having to use ``.set`` or ``.set_function``. The note here is kept for posterity and information for older versions. There are only some small caveats, see: :ref:`this note here<binding-callable-objects>`.
As of recent versions of sol3 (2.18.2 and above), this is no longer an issue, as even bound classes will have any detectable function call operator automatically bound to the object, to allow this to work without having to use ``.set`` or ``.set_function``. The note here is kept for posterity and information for older versions. There are only some small caveats, see: :ref:`this note here<binding-callable-objects>`.

View File

@ -58,7 +58,7 @@ members
template<bool check_args = stack_detail::default_check_arguments, bool clean_stack = true, typename Fx, typename... FxArgs>
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs);
This function is helpful for when you bind to a raw C function but need sol's abstractions to save you the agony of setting up arguments and know how `calling C functions works`_. The ``start`` parameter tells the function where to start pulling arguments from. The parameter ``fx`` is what's supposed to be called. Extra arguments are passed to the function directly. There are intermediate versions of this (``sol::stack::call_into_lua`` and similar) for more advanced users, but they are not documented as they are subject to change to improve performance or adjust the API accordingly in later iterations of sol2. Use the more advanced versions at your own peril.
This function is helpful for when you bind to a raw C function but need sol's abstractions to save you the agony of setting up arguments and know how `calling C functions works`_. The ``start`` parameter tells the function where to start pulling arguments from. The parameter ``fx`` is what's supposed to be called. Extra arguments are passed to the function directly. There are intermediate versions of this (``sol::stack::call_into_lua`` and similar) for more advanced users, but they are not documented as they are subject to change to improve performance or adjust the API accordingly in later iterations of sol3. Use the more advanced versions at your own peril.
.. code-block:: cpp
:caption: function: get
@ -97,7 +97,7 @@ Checks if the object at ``index`` is of type ``T``. If it is not, it will call t
template <typename T>
auto get_usertype( lua_State* L, int index, record& tracking )
Directly attempts to rertieve the type ``T`` using sol2's usertype mechanisms. Similar to a regular ``get`` for a user-defined type. Useful when you need to access sol2's usertype getter mechanism while at the same time `providing your own customization`_.
Directly attempts to rertieve the type ``T`` using sol3's usertype mechanisms. Similar to a regular ``get`` for a user-defined type. Useful when you need to access sol3's usertype getter mechanism while at the same time `providing your own customization`_.
.. code-block:: cpp
:caption: function: check_usertype
@ -112,7 +112,7 @@ Directly attempts to rertieve the type ``T`` using sol2's usertype mechanisms. S
template <typename T, typename Handler>
bool check_usertype( lua_State* L, int index, Handler&& handler, record& tracking )
Checks if the object at ``index`` is of type ``T`` and stored as a sol2 usertype. Useful when you need to access sol2's usertype checker mechanism while at the same time `providing your own customization`_.
Checks if the object at ``index`` is of type ``T`` and stored as a sol3 usertype. Useful when you need to access sol3's usertype checker mechanism while at the same time `providing your own customization`_.
.. code-block:: cpp
:caption: function: check_get
@ -160,7 +160,7 @@ Based on how it is called, pushes a variable amount of objects onto the stack. i
int multi_push_reference( lua_State* L, Args&&... args )
These functinos behave similarly to the ones above, but they check for specific criteria and instead attempt to push a reference rather than forcing a copy if appropriate. Use cautiously as sol2 uses this mainly as a return from usertype functions and variables to preserve chaining/variable semantics from that a class object. Its internals are updated to fit the needs of sol2 and while it generally does the "right thing" and has not needed to be changed for a while, sol2 reserves the right to change its internal detection mechanisms to suit its users needs at any time, generally without breaking backwards compatibility and expectations but not exactly guaranteed.
These functinos behave similarly to the ones above, but they check for specific criteria and instead attempt to push a reference rather than forcing a copy if appropriate. Use cautiously as sol3 uses this mainly as a return from usertype functions and variables to preserve chaining/variable semantics from that a class object. Its internals are updated to fit the needs of sol3 and while it generally does the "right thing" and has not needed to be changed for a while, sol3 reserves the right to change its internal detection mechanisms to suit its users needs at any time, generally without breaking backwards compatibility and expectations but not exactly guaranteed.
.. code-block:: cpp
:caption: function: pop
@ -294,7 +294,7 @@ This is an SFINAE-friendly struct that is meant to expose static function ``chec
}
};
This is an SFINAE-friendly struct that is meant to expose a function ``check=`` that returns ``true`` if a type meets some custom userdata specifiction, and ``false`` if it does not. The default implementation just returns ``false`` to let the original sol2 handlers take care of everything. If you want to implement your own usertype checking; e.g., for messing with ``toLua`` or ``OOLua`` or ``kaguya`` or some other libraries. Note that the library must have a with a :doc:`memory compatible layout<usertype_memory>` if you **want to specialize this checker method but not the subsequent getter method**. You can specialize it as shown in the `interop examples`_.
This is an SFINAE-friendly struct that is meant to expose a function ``check=`` that returns ``true`` if a type meets some custom userdata specifiction, and ``false`` if it does not. The default implementation just returns ``false`` to let the original sol3 handlers take care of everything. If you want to implement your own usertype checking; e.g., for messing with ``toLua`` or ``OOLua`` or ``kaguya`` or some other libraries. Note that the library must have a with a :doc:`memory compatible layout<usertype_memory>` if you **want to specialize this checker method but not the subsequent getter method**. You can specialize it as shown in the `interop examples`_.
.. note::
@ -308,18 +308,18 @@ This is an SFINAE-friendly struct that is meant to expose a function ``check=``
template <typename T, typename = void>
struct userdata_getter {
static std::pair<bool, T*> get ( lua_State* L, int index, void* unadjusted_pointer, record& tracking ) {
// implement custom getting here for non-sol2 userdatas:
// implement custom getting here for non-sol3 userdatas:
// if it doesn't match, return "false" and regular
// sol userdata checks will kick in
return { false, nullptr };
}
};
This is an SFINAE-friendly struct that is meant to expose a function ``get`` that returns ``true`` and an adjusted pointer if a type meets some custom userdata specifiction (from, say, another library or an internal framework). The default implementation just returns ``{ false, nullptr }`` to let the original sol2 getter take care of everything. If you want to implement your own usertype getter; e.g., for messing with ``kaguya`` or some other libraries. You can specialize it as shown in the `interop examples`_.
This is an SFINAE-friendly struct that is meant to expose a function ``get`` that returns ``true`` and an adjusted pointer if a type meets some custom userdata specifiction (from, say, another library or an internal framework). The default implementation just returns ``{ false, nullptr }`` to let the original sol3 getter take care of everything. If you want to implement your own usertype getter; e.g., for messing with ``kaguya`` or some other libraries. You can specialize it as shown in the `interop examples`_.
.. note::
You do NOT need to use this method in particular if the :doc:`memory layout<usertype_memory>` is compatible. (For example, ``toLua`` stores userdata in a sol2-compatible way.)
You do NOT need to use this method in particular if the :doc:`memory layout<usertype_memory>` is compatible. (For example, ``toLua`` stores userdata in a sol3-compatible way.)
.. note::

View File

@ -3,7 +3,7 @@ this_environment
*retrieving the environment of the calling function*
Sometimes in C++ it's useful to know where a Lua call is coming from and what :doc:`environment<environment>` it is from. The former is covered by Lua's Debug API, which is extensive and is not fully wrapped up by sol2. But, sol2 covers the latter in letting you get the environment of the calling script / function, if it has one. ``sol::this_environment`` is a *transparent argument* and does not need to be passed in Lua scripts or provided when using :doc:`sol::function<function>`, similar to :doc:`sol::this_state<this_state>`:
Sometimes in C++ it's useful to know where a Lua call is coming from and what :doc:`environment<environment>` it is from. The former is covered by Lua's Debug API, which is extensive and is not fully wrapped up by sol3. But, sol3 covers the latter in letting you get the environment of the calling script / function, if it has one. ``sol::this_environment`` is a *transparent argument* and does not need to be passed in Lua scripts or provided when using :doc:`sol::function<function>`, similar to :doc:`sol::this_state<this_state>`:
.. code-block:: cpp
:linenos:

View File

@ -132,7 +132,7 @@ If you don't specify anything at all and the type is `destructible`_, then a des
usertype automatic meta functions
+++++++++++++++++++++++++++++++++
If you don't specify a ``sol::meta_function`` name (or equivalent string metamethod name) and the type ``T`` supports certain operations, sol2 will generate the following operations provided it can find a good default implementation:
If you don't specify a ``sol::meta_function`` name (or equivalent string metamethod name) and the type ``T`` supports certain operations, sol3 will generate the following operations provided it can find a good default implementation:
* for ``to_string`` operations where ``std::ostream& operator<<( std::ostream&, const T& )``, ``obj.to_string()``, or ``to_string( const T& )`` (in the namespace) exists on the C++ type
- a ``sol::meta_function::to_string`` operator will be generated

View File

@ -12,7 +12,7 @@ In general, we always insert a ``T*`` in the first ``sizeof(T*)`` bytes, so the
.. warning::
The layout of memory described below does **not** take into account alignment. sol2 now takes alignment into account and aligns memory, which is important for misbehaving allocators and types that do not align well to the size of a pointer on their system. If you need to obtain proper alignments for usertypes stored in userdata pointers, **please** use the detail functions named ``sol::detail::align_usertype_pointer``, ``sol::detail::align_usertype``, and ``sol::detail::align_usertype_unique``. This will shift a ``void*`` pointer by the appropriate amount to reach a certain section in memory. For almost all other use cases, please use ``void* memory = lua_touserdata(L, index);``, followed by ``memory = sol::detail::align_usertype_pointer( memory );`` to adjust the pointer to be at the right place.
The layout of memory described below does **not** take into account alignment. sol3 now takes alignment into account and aligns memory, which is important for misbehaving allocators and types that do not align well to the size of a pointer on their system. If you need to obtain proper alignments for usertypes stored in userdata pointers, **please** use the detail functions named ``sol::detail::align_usertype_pointer``, ``sol::detail::align_usertype``, and ``sol::detail::align_usertype_unique``. This will shift a ``void*`` pointer by the appropriate amount to reach a certain section in memory. For almost all other use cases, please use ``void* memory = lua_touserdata(L, index);``, followed by ``memory = sol::detail::align_usertype_pointer( memory );`` to adjust the pointer to be at the right place.
.. warning::
@ -23,7 +23,7 @@ In general, we always insert a ``T*`` in the first ``sizeof(T*)`` bytes, so the
To retrieve a ``T``
-------------------
If you want to retrieve a ``T*`` pointer to the data managed by a sol2 userdata and are not using sol2's abstractions to do it (e.g., messing with the plain Lua C API), simply use ``lua_touserdata`` to get the ``void*`` pointer. Then, execute a ``T* object_pointer = *static_cast<T**>(the_void_pointer);``. Every type pushed into C++ that is classified as a userdata (e.g., all user-defined objects that are not covered by the stack abstraction's basic types) can be retrieved in this format, whether they are values or pointers or ``unique_ptr``. The reasons for why this works is below.
If you want to retrieve a ``T*`` pointer to the data managed by a sol3 userdata and are not using sol3's abstractions to do it (e.g., messing with the plain Lua C API), simply use ``lua_touserdata`` to get the ``void*`` pointer. Then, execute a ``T* object_pointer = *static_cast<T**>(the_void_pointer);``. Every type pushed into C++ that is classified as a userdata (e.g., all user-defined objects that are not covered by the stack abstraction's basic types) can be retrieved in this format, whether they are values or pointers or ``unique_ptr``. The reasons for why this works is below.
For ``T``
---------

View File

@ -8,7 +8,7 @@ Here are measurements of the *overhead that libraries impose around the Lua C AP
These are some informal and formal benchmarks done by both the developers of sol and other library developers / users. We leave you to interpret the data as you see fit.
* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`sol`_ is the "sol2" entry)
* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`sol`_ is the "sol3" entry)
* `lua-bindings-shootout`_ by ThePhD (developer of `sol`_)
As of the writing of this documentation (May 17th, 2018), :doc:`sol<index>` seems to take the cake in most categories for speed! Below are some graphs from `lua-bindings-shootout`_. You can read the benchmarking code there if you think something was done wrong, and submit a pull requests or comment on something to make sure that ThePhD is being honest about his work. All categories are the performance of things described at the top of the :doc:`feature table<features>`.

View File

@ -1,8 +1,10 @@
Build
build
=====
sol2 comes with a CMake script in the top level. It is primarily made for building and running the examples and tests, but it includes exported and configured targets (``sol2``, ``sol2_single``) for your use.
sol3 is a header-only library.
sol2 also comes with a Meson Script. If things stop working, file a bug report.
sol3 comes with a CMake script in the top level. It is primarily made for building and running the examples and tests, but it includes exported and configured targets (``sol2``, ``sol2_single``) for your use.
sol3 also comes with a Meson Script. If things stop working, file a bug report.

View File

@ -5,7 +5,7 @@ because this is surprisingly hard using standard C++
.. note::
The ``<codecvt>`` header is no longer used and sol2 now converts utf8, utf16, and utf32 with internal routines. If you have a problem with the transcoding, please `file an issue report`_.
The ``<codecvt>`` header is no longer used and sol3 now converts utf8, utf16, and utf32 with internal routines. If you have a problem with the transcoding, please `file an issue report`_.
``std::(w)string(u16/u32)`` are assumed to be in the platform's native wide (for ``wstring``) or unicode format. Lua canonically stores its string literals as utf8 and embraces utf8, albeit its storage is simply a sequence of bytes that are also null-terminated (it is also counted and the size is kept around, so embedded nulls can be used in the string). Therefore, if you need to interact with the unicode or wide alternatives of strings, runtime conversions are performed from the (assumed) utf8 string data into other forms. These conversions check for well-formed UTF, and will replace ill-formed characters with the unicode replacement codepoint, 0xFFFD.

View File

@ -26,7 +26,7 @@ GCC 7.x is now out alongside Visual Studio 2018. This means that `sol release v2
- v3.6.x
- Note: this applies to XCode's Apple Clang as well, but that compiler packs its own deficiencies and problems as well
**This does not mean we are immediately abandoning older compilers.** We will update this page as relevant bugfixes are backported to the v2.x.x releases. Remember that sol2 is feature-complete: there is nothing more we can add to the library at this time with C++11/C++14 compiler support, so your code will be covered for a long time to come.
**This does not mean we are immediately abandoning older compilers.** We will update this page as relevant bugfixes are backported to the v2.x.x releases. Remember that sol3 is feature-complete: there is nothing more we can add to the library at this time with C++11/C++14 compiler support, so your code will be covered for a long time to come.
Newer features will be targeted at the following compilers:
@ -47,9 +47,9 @@ Note that Visual Studio's 2018 Community Edition is absolutely free now, and ins
MinGW's GCC version 7.x of the compiler fixes a long-standing derp in the <codecvt> header that swapped the endianness of utf16 and utf32 strings.
Clang 3.4, 3.5 and 3.6 have many bugs we have run into when developing sol2 and that have negatively impacted users for a long time now.
Clang 3.4, 3.5 and 3.6 have many bugs we have run into when developing sol3 and that have negatively impacted users for a long time now.
We encourage all users to upgrade immediately. If you need old code for some reason, use `sol release v2.20.1`_: otherwise, always grab sol2's latest.
We encourage all users to upgrade immediately. If you need old code for some reason, use `sol release v2.20.1`_: otherwise, always grab sol3's latest.
feature support
@ -84,7 +84,7 @@ Here are some notes on achieving better compile times without sacrificing too mu
* Consider placing groups of bindings in multiple different translation units (multiple C++ source files) so that only part of the bindings are recompiled when you have to change the bindings.
- Avoid putting your bindings into headers: it *will* slow down your compilation
* If you are developing a shared library, restrict your overall surface area by specifically and explicitly marking functions as visible and exported and leaving everything else as hidden or invisible by default
* For people who already have a tool that retrieves function signatures and arguments, it might be in your best interest to hook into that tool or generator and dump out the information once using sol2's lower-level abstractions. An `issue describing preliminary steps can be found here`_.
* For people who already have a tool that retrieves function signatures and arguments, it might be in your best interest to hook into that tool or generator and dump out the information once using sol3's lower-level abstractions. An `issue describing preliminary steps can be found here`_.
next steps

View File

@ -47,7 +47,7 @@ master_doc = 'index'
# General information about the project.
project = 'Sol'
copyright = '2018, ThePhD'
copyright = '2019, ThePhD'
author = 'ThePhD'
# The version info for the project you're documenting, acts as replacement for
@ -57,7 +57,7 @@ author = 'ThePhD'
# The short X.Y version.
version = '3.0'
# The full version, including alpha/beta/rc tags.
release = '3.0.0'
release = '3.0.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -1,8 +1,8 @@
containers
==========
*working with containers in sol2*
*working with containers in sol3*
Containers are objects that are meant to be inspected and iterated and whose job is to typically provide storage to a collection of items. The standard library has several containers of varying types, and all of them have ``begin()`` and ``end()`` methods which return iterators. C-style arrays are also containers, and sol2 will detect all of them for use and bestow upon them special properties and functions.
Containers are objects that are meant to be inspected and iterated and whose job is to typically provide storage to a collection of items. The standard library has several containers of varying types, and all of them have ``begin()`` and ``end()`` methods which return iterators. C-style arrays are also containers, and sol3 will detect all of them for use and bestow upon them special properties and functions.
* Containers from C++ are stored as ``userdata`` with special ``usertype`` metatables with :ref:`special operations<container-operations>`
- In Lua 5.1, this means containers pushed without wrappers like :doc:`as_table<api/as_table>` and :doc:`nested<api/nested>` will not work with ``pairs`` or other built-in iteration functions from Lua
@ -27,7 +27,7 @@ Containers are objects that are meant to be inspected and iterated and whose job
container detection
-------------------
containers are detected by the type trait ``sol::is_container<T>``. If that turns out to be true, sol2 will attempt to push a userdata into Lua for the specified type ``T``, and bestow it with some of the functions and properties listed below. These functions and properties are provided by a template struct ``sol::container_traits<T>``, which has a number of static Lua C functions bound to a safety metatable. If you want to override the behavior for a specific container, you must first specialize ``sol::is_container<T>`` to drive from ``std::true_type``, then override the functions you want to change. Any function you do not override will call the default implementation or equivalent. The default implementation for unrecognized containers is simply errors.
containers are detected by the type trait ``sol::is_container<T>``. If that turns out to be true, sol3 will attempt to push a userdata into Lua for the specified type ``T``, and bestow it with some of the functions and properties listed below. These functions and properties are provided by a template struct ``sol::container_traits<T>``, which has a number of static Lua C functions bound to a safety metatable. If you want to override the behavior for a specific container, you must first specialize ``sol::is_container<T>`` to drive from ``std::true_type``, then override the functions you want to change. Any function you do not override will call the default implementation or equivalent. The default implementation for unrecognized containers is simply errors.
You can also specialize ``sol::is_container<T>`` to turn off container detection, if you find it too eager for a type that just happens to have ``begin`` and ``end`` functions, like so:
@ -178,7 +178,7 @@ Below are the many container operations and their override points for ``containe
container classifications
-------------------------
When you serialize a container into sol2, the default container handler deals with the containers by inspecting various properties, functions, and typedefs on them. Here are the broad implications of containers sol2's defaults will recognize, and which already-known containers fall into their categories:
When you serialize a container into sol3, the default container handler deals with the containers by inspecting various properties, functions, and typedefs on them. Here are the broad implications of containers sol3's defaults will recognize, and which already-known containers fall into their categories:
+------------------------+----------------------------------------+-------------------------+-----------------------------------------------------------------------------------------------+
| container type | requirements | known containers | notes/caveats |

View File

@ -55,7 +55,7 @@ Linker Errors
There are lots of reasons for compiler linker errors. A common one is not knowing that you've compiled the Lua library as C++: when building with C++, it is important to note that every typical (static or dynamic) library expects the C calling convention to be used and that Sol includes the code using ``extern 'C'`` where applicable.
However, when the target Lua library is compiled with C++, one must change the calling convention and name mangling scheme by getting rid of the ``extern 'C'`` block. This can be achieved by adding ``#define SOL_USING_CXX_LUA`` before including sol2, or by adding it to your compilation's command line. If you build LuaJIT in C++ mode (how you would even, is beyond me), then you need to ``#define SOL_USING_CXX_LUAJIT`` as well. Typically, there is never a need to use this last one.
However, when the target Lua library is compiled with C++, one must change the calling convention and name mangling scheme by getting rid of the ``extern 'C'`` block. This can be achieved by adding ``#define SOL_USING_CXX_LUA`` before including sol3, or by adding it to your compilation's command line. If you build LuaJIT in C++ mode (how you would even, is beyond me), then you need to ``#define SOL_USING_CXX_LUAJIT`` as well. Typically, there is never a need to use this last one.
Note that you should not be defining these with standard builds of either Lua or LuaJIT. See the :ref:`config page<config-linker>` for more details.
@ -64,7 +64,7 @@ Note that you should not be defining these with standard builds of either Lua or
Sometimes, you expect properly written errors and instead receive an error about catching a ``...`` exception instead. This might mean that you either built Lua as C++ or are using a framework like LuaJIT that has full interopability support for exceptions on certain system types (x64 for LuaJIT 2.0.5, x86 and x64 on LuaJIT 2.1.x-beta and later).
Please make sure to use the ``SOL_EXCEPTIONS_SAFE_PROPAGATION`` define before including sol2 to make this work out. You can read more :ref:`at the exception page here<exception-interop>`.
Please make sure to use the ``SOL_EXCEPTIONS_SAFE_PROPAGATION`` define before including sol3 to make this work out. You can read more :ref:`at the exception page here<exception-interop>`.
Catch and CRASH!
----------------
@ -73,7 +73,7 @@ By default, Sol will add a ``default_at_panic`` handler to states opened by Sol
It is preferred if you catch an error that you log what happened, terminate the Lua VM as soon as possible, and then crash if your application cannot handle spinning up a new Lua state. Catching can be done, but you should understand the risks of what you're doing when you do it. For more information about catching exceptions, the potentials, not turning off exceptions and other tricks and caveats, read about :doc:`exceptions in Sol here<exceptions>`.
Lua is a C API first and foremost: exceptions bubbling out of it is essentially last-ditch, terminal behavior that the VM does not expect. You can see an example of handling a panic on the exceptions page :ref:`here<typical-panic-function>`. This means that setting up a ``try { ... } catch (...) {}`` around an unprotected sol2 function or script call is **NOT** enough to keep the VM in a clean state. Lua does not understand exceptions and throwing them results in undefined behavior if they bubble through the C API once and then the state is used again. Please catch, and crash.
Lua is a C API first and foremost: exceptions bubbling out of it is essentially last-ditch, terminal behavior that the VM does not expect. You can see an example of handling a panic on the exceptions page :ref:`here<typical-panic-function>`. This means that setting up a ``try { ... } catch (...) {}`` around an unprotected sol3 function or script call is **NOT** enough to keep the VM in a clean state. Lua does not understand exceptions and throwing them results in undefined behavior if they bubble through the C API once and then the state is used again. Please catch, and crash.
Furthermore, it would be a great idea for you to use the safety features talked about :doc:`safety section<safety>`, especially for those related to functions.
@ -94,7 +94,7 @@ By default, :doc:`sol::function<api/function>` assumes the code ran just fine an
Protected Functions Are Not Catch All
-------------------------------------
Sometimes, some scripts load poorly. Even if you protect the function call, the actual file loading or file execution will be bad, in which case :doc:`sol::protected_function<api/protected_function>` will not save you. Make sure you register your own panic handler so you can catch errors, or follow the advice of the catch + crash behavior above. Remember that you can also bind your own functions and forego sol2's built-in protections for you own by binding a :ref:`raw lua_CFunction function<raw-function-note>`
Sometimes, some scripts load poorly. Even if you protect the function call, the actual file loading or file execution will be bad, in which case :doc:`sol::protected_function<api/protected_function>` will not save you. Make sure you register your own panic handler so you can catch errors, or follow the advice of the catch + crash behavior above. Remember that you can also bind your own functions and forego sol3's built-in protections for you own by binding a :ref:`raw lua_CFunction function<raw-function-note>`
Iteration
---------

View File

@ -32,7 +32,7 @@ Lua comes with two kind of built-in handlers that sol provides easy opt-ins for.
:linenos:
The other handler is specific to sol2. If you open a ``sol::state``, or open the default state handlers for your ``lua_State*`` (see :ref:`sol::state's automatic handlers<state-automatic-handlers>` for more details), there is a ``sol::exception_handler_function`` type. It allows you to register a function in the event that an exception happens that bubbles out of your functions. The function requires that you push 1 item onto the stack that will be used with a call to `lua_error`_
The other handler is specific to sol3. If you open a ``sol::state``, or open the default state handlers for your ``lua_State*`` (see :ref:`sol::state's automatic handlers<state-automatic-handlers>` for more details), there is a ``sol::exception_handler_function`` type. It allows you to register a function in the event that an exception happens that bubbles out of your functions. The function requires that you push 1 item onto the stack that will be used with a call to `lua_error`_
.. literalinclude:: ../../examples/source/exception_handler.cpp
:caption: exception handling

View File

@ -92,7 +92,7 @@ Explanations for a few categories are below (rest are self-explanatory).
* environments: an abstraction for getting, setting and manipulating an environment, using table techniques, functions or otherwise. Typically for the purposes of sandboxing
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| | plain C | luawrapper | lua-intf | luabind | Selene | Sol2 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra |
| | plain C | luawrapper | lua-intf | luabind | Selene | Sol3 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra |
| | | | | | | | | | | | | | |
+===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+========+
| optional | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ |

View File

@ -1,13 +1,13 @@
functions
=========
*working with functions in sol2*
*working with functions in sol3*
There are a number of examples dealing with functions and how they can be bound to sol2:
There are a number of examples dealing with functions and how they can be bound to sol3:
* For a quicker walkthrough that demonstrates almost everything, see `the examples`_ and the :doc:`the quick and dirty tutorial<tutorial/all-the-things>`
* For a full explanation, :doc:`read the tutorial<tutorial/functions>` and consult the subjects below
* If you have bindings and set-ups that want to leverage the C API without sol2's interference, you can push a raw function, which has certain implications (noted :ref:`below<raw-function-note>`)
* If you have bindings and set-ups that want to leverage the C API without sol3's interference, you can push a raw function, which has certain implications (noted :ref:`below<raw-function-note>`)
* Return multiple values into Lua by:
- returning a ``std::tuple``
- using :doc:`sol::variadic_results<api/variadic_results>`
@ -21,7 +21,7 @@ There are a number of examples dealing with functions and how they can be bound
- :doc:`sol::this_environment<api/this_environment>`, for potentially retrieving the current Lua environment
* Control serialization of arguments and return types with :doc:`sol::nested<api/nested>`, :doc:`sol::as_table<api/nested>`, :doc:`sol::as_args<api/as_args>` and :doc:`sol::as_function<api/as_function>`
* Set environments for Lua functions and scripts with :doc:`sol::environment<api/environment>`
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
* You can use :doc:`policies<api/policies>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
@ -51,7 +51,7 @@ Furthermore, it is important to know that lambdas without a specified return typ
exception safety/handling
-------------------------
All functions bound to sol2 set up an exception trampoline around the function (unless you are working with a :ref:`raw lua_CFunction you pushed yourself<raw-function-note>`). :doc:`protected_function<api/protected_function>` also has an error handler member and an exception trampoline around its internals, but it is not guaranteed safe if an exception bubbles outside of it. Catching that exception is not safe either: if an exception has exploded out from the sol2 API somehow, you must assume the VM is in some indeterminate and/or busted state.
All functions bound to sol3 set up an exception trampoline around the function (unless you are working with a :ref:`raw lua_CFunction you pushed yourself<raw-function-note>`). :doc:`protected_function<api/protected_function>` also has an error handler member and an exception trampoline around its internals, but it is not guaranteed safe if an exception bubbles outside of it. Catching that exception is not safe either: if an exception has exploded out from the sol3 API somehow, you must assume the VM is in some indeterminate and/or busted state.
Please read the :doc:`error page<errors>` and :doc:`exception page<exceptions>` for more details about what to do with exceptions that explode out from the API.
@ -68,11 +68,11 @@ All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state<api/s
This also means that you should pass and receive arguments in certain ways to maximize efficiency. For example, ``sol::table``, ``sol::object``, ``sol::userdata`` and friends are cheap to copy, and should simply by taken as values. This includes primitive types like ``int`` and ``double``. However, C++ types -- if you do not want copies -- should be taken as ``const type&`` or ``type&``, to save on copies if it's important. Note that taking references from Lua also means you can modify the data inside of Lua directly, so be careful. Lua by default deals with things mostly by reference (save for primitive types).
When you bind a function to Lua, please take any pointer arguments as ``T*``, unless you specifically know you are going to match the exact type of the unique/shared pointer and the class it wraps. sol2 cannot support "implicit wrapped pointer casting", such as taking a ``std::shared_ptr<MySecondBaseClass>`` when the function is passed a ``std::shared_ptr<MyDerivedClass>``. Sometimes it may work because the compiler might be able to line up your classes in such a way that raw casts work, but this is undefined behavior through and through and sol2 has no mechanisms by which it can make this safe and not blow up in the user's face.
When you bind a function to Lua, please take any pointer arguments as ``T*``, unless you specifically know you are going to match the exact type of the unique/shared pointer and the class it wraps. sol3 cannot support "implicit wrapped pointer casting", such as taking a ``std::shared_ptr<MySecondBaseClass>`` when the function is passed a ``std::shared_ptr<MyDerivedClass>``. Sometimes it may work because the compiler might be able to line up your classes in such a way that raw casts work, but this is undefined behavior through and through and sol3 has no mechanisms by which it can make this safe and not blow up in the user's face.
.. note::
Please avoid taking special unique_usertype arguments, by either reference or value. In many cases, by-value does not work (e.g., with ``std::unique_ptr``) because many types are move-only and Lua has no concept of "move" semantics. By-reference is dangerous because sol2 will hand you a reference to the original data: but, any pointers stored in Lua can be invalidated if you call ``.reset()`` or similar on the core pointer. Please take a pointer (``T*``) if you anticipate ``nil``/``nullptr`` being passed to your function, or a reference (``const T&`` or ``T&``) if you do not. As a side note, if you write a small wrapping class that holds a base pointer type, and interact using the wrapper, then when you get the wrapper as an argument in a C++-function bound to Lua you can cast the internal object freely. It is simply a direct cast as an argument to a function that is the problem.
Please avoid taking special unique_usertype arguments, by either reference or value. In many cases, by-value does not work (e.g., with ``std::unique_ptr``) because many types are move-only and Lua has no concept of "move" semantics. By-reference is dangerous because sol3 will hand you a reference to the original data: but, any pointers stored in Lua can be invalidated if you call ``.reset()`` or similar on the core pointer. Please take a pointer (``T*``) if you anticipate ``nil``/``nullptr`` being passed to your function, or a reference (``const T&`` or ``T&``) if you do not. As a side note, if you write a small wrapping class that holds a base pointer type, and interact using the wrapper, then when you get the wrapper as an argument in a C++-function bound to Lua you can cast the internal object freely. It is simply a direct cast as an argument to a function that is the problem.
.. note::

View File

@ -45,6 +45,32 @@ get going:
origin
connect
--------
Come to the Github Issues or the Discord! We've got a friendly community, and they can help you out or you can come just to talk about the things you are working on!
|ds| |gh|
support
-------
You can support the project and other related endeavors in various ways.
|pa| |kf| |lp| |pp|
You can support sol3 development by using any of the above. This is a time-consuming effort, so individuals who donate get to:
- steer the direction and time spent on sol
- get a role on the Discord server
- get their name put up in the CONTRIBUTORS list
- put something of their choice on sol3's README or the documentation's front page
You can also help out the library by submitting pull requests to fix anything or add anything you think would be helpful! This includes making small, useful examples of something you haven't seen, or fixing typos and bad code in the documentation.
"I need feature X, maybe you have it?"
--------------------------------------
Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. To know more about the implementation for usertypes, see :doc:`here<usertypes>` To know how function arguments are handled, see :ref:`this note<function-argument-handling>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker.
@ -54,7 +80,7 @@ the basics:
-----------
.. note::
The code below *and* more examples can be found in the `examples directory`_
The code below *and* more examples can be found in the `examples directory`_.
.. literalinclude:: ../../examples/source/docs/simple_functions.cpp
@ -66,20 +92,6 @@ the basics:
:linenos:
helping out
-----------
You can support sol2 development by `donating here`_. This is a time-consuming effort, so individuals who donate get to:
- steer the direction and time spent on sol
- get a role on the Discord server
- get their name put up in the CONTRIBUTORS list
- put something of their choice on sol2's README or the documentation's front page
You can also help out the library by submitting pull requests to fix anything or add anything you think would be helpful! This includes making small, useful examples of something you haven't seen, or fixing typos and bad code in the documentation.
Finally, `come join in Discord`_!
Indices and tables
==================
@ -89,5 +101,37 @@ Indices and tables
.. _Sol: https://github.com/ThePhD/sol2
.. _issues: https://github.com/ThePhD/sol2/issues
.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples
.. _donating here: https://www.paypal.me/LMeneide
.. _come join in Discord: https://discord.gg/buxkYNT
.. |pa| image:: media/become_a_patron_button.png
:height: 50
:target: https://www.patreon.com/thephd
:alt: sol3 Patreon
:align: middle
.. |kf| image:: media/Ko-fi_Blue.png
:height: 50
:target: https://ko-fi.com/thephd
:alt: sol3 ko-fi
:align: middle
.. |lp| image:: media/liberapay_logo.png
:height: 50
:target: https://ko-fi.com/thephd
:alt: sol3 ko-fi
:align: middle
.. |pp| image:: media/pp_cc_mark_111x69.jpg
:height: 50
:target: https://www.paypal.me/thephd
:alt: sol3 PayPal
:align: middle
.. |ds| image:: media/discord_logo_wordmark.png
:height: 75
:target: https://discord.gg/buxkYNT
:alt: sol3 Discord
.. |gh| image:: media/github_logo.png
:height: 75
:target: https://github.com/ThePhD/sol2/issues
:alt: sol3 Github Issues Page

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -4,9 +4,9 @@ mentions
First off, feel free to `tell me about your uses!`_
Okay, so the features don't convince you, the documentation doesn't convince you, you want to see what *other* people think about Sol? Well, aside from the well-wishes that come through in the issue tracker, here's a few things floating around about sol2 that I occasionally get pinged about:
Okay, so the features don't convince you, the documentation doesn't convince you, you want to see what *other* people think about Sol? Well, aside from the well-wishes that come through in the issue tracker, here's a few things floating around about sol3 that I occasionally get pinged about:
`eevee`_ demonstrating the sheer code reduction by using sol2:
`eevee`_ demonstrating the sheer code reduction by using sol3:
.. |before| image:: media/eevee_code_before.jpg
@ -16,7 +16,7 @@ Okay, so the features don't convince you, the documentation doesn't convince you
.. |after| image:: media/eevee_code_after.jpg
:target: https://twitter.com/eevee/status/762039984085798913
:alt: Now with sol2!
:alt: Now with sol3!
:align: middle
+----------+---------+
@ -24,10 +24,10 @@ Okay, so the features don't convince you, the documentation doesn't convince you
+----------+---------+
* In `High Performance Computing research`_
* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol2!
* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol3!
- `The pull request`_ in which it was introduced to the master branch.
* For scripting, in `OpenMPT`_
* (CppNow) sol2 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference!
* (CppNow) sol3 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference!
- `Jason Turner's presentation`_
* (CppCast) Showed up in CppCast with Elias Daler!
- `Elias Daler's blog`_
@ -36,16 +36,16 @@ Okay, so the features don't convince you, the documentation doesn't convince you
- `eevee's blog`_
* (Twitter) Twitter has some people that link it:
- The image above, `tweeted out by eevee`_
- Eevee: `"I heartily recommend sol2"`_
- Elias Daler: `"sol2 saved my life."`_
- Racod's Lair: `"from outdated LuaBridge to superior #sol2"`_
- Eevee: `"I heartily recommend sol3"`_
- Elias Daler: `"sol3 saved my life."`_
- Racod's Lair: `"from outdated LuaBridge to superior #sol3"`_
* (Reddit) Posts on reddit about it!
- `sol2's initial reddit release`_
- `sol3's initial reddit release`_
- `Benchmarking Discussing`_
* Somehow landed on a Torque3D thread...
- http://forums.torque3d.org/viewtopic.php?f=32&t=629&p=5246&sid=8e759990ab1ce38a48e896fc9fd62653#p5241
Are you using sol2 for something neat? Want it to be featured here or think it's unfair that ThePhD hasn't found it yet? Well, drop an issue in the repo or send an e-mail!
Are you using sol3 for something neat? Want it to be featured here or think it's unfair that ThePhD hasn't found it yet? Well, drop an issue in the repo or send an e-mail!
.. _tell me about your uses!: https://github.com/ThePhD/sol2/issues/189
.. _eevee: https://twitter.com/eevee
@ -54,11 +54,11 @@ Are you using sol2 for something neat? Want it to be featured here or think it's
.. _Elias Daler's blog: https://eliasdaler.github.io/cppcast#read-more
.. _CppCast: http://cppcast.com/2016/07/elias-daler/
.. _tweeted out by eevee: https://twitter.com/eevee/status/762039984085798913
.. _"I heartily recommend sol2": https://twitter.com/eevee/status/762040086540144644
.. _"from outdated LuaBridge to superior #sol2": https://twitter.com/racodslair/status/754031870640267264
.. _sol2's initial reddit release: https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/
.. _"I heartily recommend sol3": https://twitter.com/eevee/status/762040086540144644
.. _"from outdated LuaBridge to superior #sol3": https://twitter.com/racodslair/status/754031870640267264
.. _sol3's initial reddit release: https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/
.. _Benchmarking Discussing: https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/
.. _"sol2 saved my life.": https://twitter.com/EliasDaler/status/739215685264494593
.. _"sol3 saved my life.": https://twitter.com/EliasDaler/status/739215685264494593
.. _Multiple Arcade Machine Emulator (MAME): http://www.mamedev.org/index.php
.. _The pull request: https://github.com/mamedev/mame/pull/1626
.. _OpenMPT: https://openmpt.org/

View File

@ -13,7 +13,7 @@ And lo, `Danny Y., Rapptz`_ did stand firm in the sea and cast his hands to the
seriously
---------
Sol was originally started by many moon cycles ago to interop with Lua and C++, by `Rapptz`_. It was very successful and many rejoiced at having an easy to use abstraction on top of the Lua API. Rapptz continued to make a number of great projects and has been busy with other things, so upon seeing the repository grow stagnant and tired in the last very long while (over a year), `ThePhD`_ forked it into Sol2 and rebooted the code with the hopes of reaching the Milestone and the documentation you have today.
Sol was originally started by many moon cycles ago to interop with Lua and C++, by `Rapptz`_. It was very successful and many rejoiced at having an easy to use abstraction on top of the Lua API. Rapptz continued to make a number of great projects and has been busy with other things, so upon seeing the repository grow stagnant and tired in the last very long while (over a year), `ThePhD`_ forked it into Sol3 and rebooted the code with the hopes of reaching the Milestone and the documentation you have today.
To get to the old repo, head over `here`_.

View File

@ -10,7 +10,7 @@ config
Note that you can obtain safety with regards to functions you bind by using the :doc:`protect<api/protect>` wrapper around function/variable bindings you set into Lua. Additionally, you can have basic boolean checks when using the API by just converting to a :doc:`sol::optional\<T><api/optional>` when necessary for getting things out of Lua and for function arguments.
Also note that you can have your own states use sol2's safety panics and similar to protect your code from crashes. See :ref:`sol::state automatic handlers<state-automatic-handlers>` for more details.
Also note that you can have your own states use sol3's safety panics and similar to protect your code from crashes. See :ref:`sol::state automatic handlers<state-automatic-handlers>` for more details.
.. _config-safety:
@ -64,7 +64,7 @@ Safety Config
``SOL_STRINGS_ARE_NUMBERS`` triggers the following changes:
* Allows automatic to-string conversions for numbers
- ``lua_tolstring`` conversions are not permitted on numbers through sol2 by default: only actual strings are allowed
- ``lua_tolstring`` conversions are not permitted on numbers through sol3 by default: only actual strings are allowed
- This is necessary to allow :doc:`sol::overload<api/overload>` to work properly
* ``sol::stack::get`` and ``sol::stack::check_get`` will allow anything that Lua thinks is number-worthy to be number-worthy
* This includes: integers, floating-point numbers, and strings
@ -142,7 +142,7 @@ Memory safety can be tricky. Lua is handled by a garbage-collected runtime, mean
The usertype memory layout for all Lua-instantiated userdata and for all objects pushed/set into the Lua Runtime is also described :doc:`here<api/usertype_memory>`. Things before or after that specified memory slot is implementation-defined and no assumptions are to be made about it.
Please be wary of alignment issues. sol2 **aligns memory** by default. If you need to access underlying userdata memory from sol, please see the :doc:`usertype memory documentation<api/usertype_memory>`
Please be wary of alignment issues. sol3 **aligns memory** by default. If you need to access underlying userdata memory from sol, please see the :doc:`usertype memory documentation<api/usertype_memory>`
functions
---------

View File

@ -1,7 +1,7 @@
customization traits
====================
These are customization points within the library to help you make sol2 work for the types in your framework and types.
These are customization points within the library to help you make sol3 work for the types in your framework and types.
To learn more about various customizable traits, visit:

View File

@ -9,16 +9,16 @@ These are all the things. Use your browser's search to find things you want.
.. note::
All of the code below is available at the `sol2 tutorial examples`_.
All of the code below is available at the `sol3 tutorial examples`_.
asserts / prerequisites
-----------------------
You'll need to ``#include <sol/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.
You'll need to ``#include <sol/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/source/assert.hpp
.. literalinclude:: ../../../examples/include/assert.hpp
:linenos:
:lines: 1-3, 19-
@ -33,10 +33,10 @@ opening a state
.. _sol-state-on-lua-state:
using sol2 on a lua_State\*
using sol3 on a lua_State\*
---------------------------
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:
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 sol3 and nice things:
.. literalinclude:: ../../../examples/source/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp
@ -278,4 +278,4 @@ Some more things you can do/read about:
.. _basic example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype.cpp
.. _special functions example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_special_functions.cpp
.. _initializers example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_initializers.cpp
.. _sol2 tutorial examples: https://github.com/ThePhD/sol2/tree/develop/examples/tutorials/quick_n_dirty
.. _sol3 tutorial examples: https://github.com/ThePhD/sol2/tree/develop/examples/tutorials/quick_n_dirty

View File

@ -1,7 +1,7 @@
usertypes
=========
Perhaps the most powerful feature of sol2, ``usertypes`` are the way sol2 and C++ communicate your classes to the Lua runtime and bind things between both tables and to specific blocks of C++ memory, allowing you to treat Lua userdata and other things like classes.
Perhaps the most powerful feature of sol3, ``usertypes`` are the way sol3 and C++ communicate your classes to the Lua runtime and bind things between both tables and to specific blocks of C++ memory, allowing you to treat Lua userdata and other things like classes.
To learn more about usertypes, visit:
@ -19,7 +19,7 @@ The examples folder also has a number of really great examples for you to see. T
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
* You can use :doc:`policies<api/policies>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
* You can work with special wrapper types such as ``std::unique_ptr<T>``, ``std::shared_ptr<T>``, and others by default
- Extend them using the :doc:`sol::unique_usertype\<T\> traits<api/unique_usertype_traits>`
- This allows for custom smart pointers, special pointers, custom handles and others to be given certain handling semantics to ensure proper RAII with Lua's garbage collection
@ -30,7 +30,7 @@ The examples folder also has a number of really great examples for you to see. T
.. _usertype-special-features:
.. note::
Note that to use many of sol2's features, such as automatic constructor creation, ``sol::property``, and similar, one must pass these things to the usertype as part of its initial creation and grouping of arguments. Attempting to do so afterwards will result in unexpected and wrong behavior, as the system will be missing information it needs. This is because many of these features rely on ``__index`` and ``__newindex`` Lua metamethods being overridden and handled in a special way!
Note that to use many of sol3's features, such as automatic constructor creation, ``sol::property``, and similar, one must pass these things to the usertype as part of its initial creation and grouping of arguments. Attempting to do so afterwards will result in unexpected and wrong behavior, as the system will be missing information it needs. This is because many of these features rely on ``__index`` and ``__newindex`` Lua metamethods being overridden and handled in a special way!
Here are some other general advice and tips for understanding and dealing with usertypes:
@ -50,14 +50,14 @@ Here are some other general advice and tips for understanding and dealing with u
- Retrieve a plain ``T`` to get a copy
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol3's will be called to add that function to the usertype's function/variable lookup table
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi"); end`` will instead set the key ``hi`` to to lookup that function for all ``test`` types
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol2, making it easy to interop with select other Lua systems.
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol3, making it easy to interop with select other Lua systems.
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
- Work on a copy by taking arguments or returning by value.
- Do not use r-value references: they do not mean anything in Lua code.
- Move-only types can only be taken by reference: sol2 cannot know if/when to move a value (except when serializing with perfect forwarding *into* Lua, but not calling a C++ function from Lua)
- Move-only types can only be taken by reference: sol3 cannot know if/when to move a value (except when serializing with perfect forwarding *into* Lua, but not calling a C++ function from Lua)
* The actual metatable associated with the usertype has a long name and is defined to be opaque by the Sol implementation.
* The actual metatable inner workings is opaque and defined by the Sol implementation, and there are no internal docs because optimizations on the operations are applied based on heuristics we discover from performance testing the system.

View File

@ -28,7 +28,7 @@
#include "protect.hpp"
#include "wrapper.hpp"
#include "trampoline.hpp"
#include "filters.hpp"
#include "policies.hpp"
#include "stack.hpp"
#include "unique_usertype_traits.hpp"
@ -37,9 +37,9 @@ namespace sol {
} // namespace u_detail
namespace filter_detail {
namespace policy_detail {
template <int I, int... In>
inline void handle_filter(static_stack_dependencies<I, In...>, lua_State* L, int&) {
inline void handle_policy(static_stack_dependencies<I, In...>, lua_State* L, int&) {
if constexpr (sizeof...(In) == 0) {
(void)L;
return;
@ -65,12 +65,12 @@ namespace sol {
}
template <int... In>
inline void handle_filter(returns_self_with<In...>, lua_State* L, int& pushed) {
inline void handle_policy(returns_self_with<In...>, lua_State* L, int& pushed) {
pushed = stack::push(L, raw_index(1));
handle_filter(static_stack_dependencies<-1, In...>(), L, pushed);
handle_policy(static_stack_dependencies<-1, In...>(), L, pushed);
}
inline void handle_filter(const stack_dependencies& sdeps, lua_State* L, int&) {
inline void handle_policy(const stack_dependencies& sdeps, lua_State* L, int&) {
absolute_index ai(L, sdeps.target);
if (type_of(L, ai) != type::userdata) {
return;
@ -87,11 +87,11 @@ namespace sol {
lua_setuservalue(L, ai);
}
template <typename P, meta::disable<std::is_base_of<detail::filter_base_tag, meta::unqualified_t<P>>> = meta::enabler>
inline void handle_filter(P&& p, lua_State* L, int& pushed) {
template <typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler>
inline void handle_policy(P&& p, lua_State* L, int& pushed) {
pushed = std::forward<P>(p)(L, pushed);
}
} // namespace filter_detail
} // namespace policy_detail
namespace function_detail {
inline int no_construction_error(lua_State* L) {
@ -807,14 +807,14 @@ namespace sol {
}
};
template <typename T, typename F, typename... Filters, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, filter_wrapper<F, Filters...>, is_index, is_variable, checked, boost, clean_stack, C> {
typedef filter_wrapper<F, Filters...> P;
template <typename T, typename F, typename... Policies, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, policy_wrapper<F, Policies...>, is_index, is_variable, checked, boost, clean_stack, C> {
typedef policy_wrapper<F, Policies...> P;
template <std::size_t... In>
static int call(std::index_sequence<In...>, lua_State* L, P& fx) {
int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C>{}.call(L, fx.value);
(void)detail::swallow{ int(), (filter_detail::handle_filter(std::get<In>(fx.filters), L, pushed), int())... };
(void)detail::swallow{ int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... };
return pushed;
}
@ -888,8 +888,8 @@ namespace sol {
template <typename T>
struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> {};
template <typename F, typename... Filters>
struct is_var_bind<filter_wrapper<F, Filters...>> : is_var_bind<meta::unqualified_t<F>> {};
template <typename F, typename... Policies>
struct is_var_bind<policy_wrapper<F, Policies...>> : is_var_bind<meta::unqualified_t<F>> {};
} // namespace call_detail
template <typename T>

View File

@ -187,8 +187,8 @@ namespace sol {
struct as_args_t;
template <typename T>
struct protect_t;
template <typename F, typename... Filters>
struct filter_wrapper;
template <typename F, typename... Policies>
struct policy_wrapper;
template <typename T>
struct usertype_traits;

View File

@ -564,9 +564,9 @@ namespace sol {
}
};
template <typename F, typename... Filters>
struct unqualified_pusher<filter_wrapper<F, Filters...>> {
using P = filter_wrapper<F, Filters...>;
template <typename F, typename... Policies>
struct unqualified_pusher<policy_wrapper<F, Policies...>> {
using P = policy_wrapper<F, Policies...>;
static int push(lua_State* L, const P& p) {
lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
@ -585,9 +585,9 @@ namespace sol {
}
};
template <typename T, typename F, typename... Filters>
struct unqualified_pusher<detail::tagged<T, filter_wrapper<F, Filters...>>> {
using P = filter_wrapper<F, Filters...>;
template <typename T, typename F, typename... Policies>
struct unqualified_pusher<detail::tagged<T, policy_wrapper<F, Policies...>>> {
using P = policy_wrapper<F, Policies...>;
using Tagged = detail::tagged<T, P>;
static int push(lua_State* L, const Tagged& p) {

View File

@ -30,17 +30,17 @@
namespace sol {
namespace detail {
struct filter_base_tag {};
struct policy_base_tag {};
} // namespace detail
template <int Target, int... In>
struct static_stack_dependencies : detail::filter_base_tag {};
struct static_stack_dependencies : detail::policy_base_tag {};
typedef static_stack_dependencies<-1, 1> self_dependency;
template <int... In>
struct returns_self_with : detail::filter_base_tag {};
struct returns_self_with : detail::policy_base_tag {};
typedef returns_self_with<> returns_self;
struct stack_dependencies : detail::filter_base_tag {
struct stack_dependencies : detail::policy_base_tag {
int target;
std::array<int, 64> stack_indices;
std::size_t len;
@ -65,35 +65,35 @@ namespace sol {
}
};
template <typename F, typename... Filters>
struct filter_wrapper {
typedef std::index_sequence_for<Filters...> indices;
template <typename F, typename... Policies>
struct policy_wrapper {
typedef std::index_sequence_for<Policies...> indices;
F value;
std::tuple<Filters...> filters;
std::tuple<Policies...> policies;
template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, filter_wrapper>>> = meta::enabler>
filter_wrapper(Fx&& fx, Args&&... args)
: value(std::forward<Fx>(fx)), filters(std::forward<Args>(args)...) {
template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, policy_wrapper>>> = meta::enabler>
policy_wrapper(Fx&& fx, Args&&... args)
: value(std::forward<Fx>(fx)), policies(std::forward<Args>(args)...) {
}
filter_wrapper(const filter_wrapper&) = default;
filter_wrapper& operator=(const filter_wrapper&) = default;
filter_wrapper(filter_wrapper&&) = default;
filter_wrapper& operator=(filter_wrapper&&) = default;
policy_wrapper(const policy_wrapper&) = default;
policy_wrapper& operator=(const policy_wrapper&) = default;
policy_wrapper(policy_wrapper&&) = default;
policy_wrapper& operator=(policy_wrapper&&) = default;
};
template <typename F, typename... Args>
auto filters(F&& f, Args&&... args) {
return filter_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...);
auto policies(F&& f, Args&&... args) {
return policy_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...);
}
namespace detail {
template <typename T>
using is_filter = meta::is_specialization_of<T, filter_wrapper>;
using is_policy = meta::is_specialization_of<T, policy_wrapper>;
template <typename T>
inline constexpr bool is_filter_v = is_filter<T>::value;
inline constexpr bool is_policy_v = is_policy<T>::value;
}
} // namespace sol

View File

@ -28,7 +28,7 @@
#include "raii.hpp"
#include "optional.hpp"
#include "usertype_traits.hpp"
#include "filters.hpp"
#include "policies.hpp"
#include "unicode.hpp"
#include <memory>

View File

@ -478,7 +478,7 @@ namespace sol {
constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
auto pp = stack::push_pop<global>(*this);
lua_State* L = base_t::lua_state();
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...);
return *this;
}

View File

@ -32,7 +32,7 @@
#include "traits.hpp"
#include "string_view.hpp"
#include "raii.hpp"
#include "filters.hpp"
#include "policies.hpp"
#include "ebco.hpp"
#include <array>
@ -1332,8 +1332,8 @@ namespace sol {
template <typename T>
struct is_constructor<protect_t<T>> : is_constructor<meta::unqualified_t<T>> {};
template <typename F, typename... Filters>
struct is_constructor<filter_wrapper<F, Filters...>> : is_constructor<meta::unqualified_t<F>> {};
template <typename F, typename... Policies>
struct is_constructor<policy_wrapper<F, Policies...>> : is_constructor<meta::unqualified_t<F>> {};
template <typename T>
inline constexpr bool is_constructor_v = is_constructor<T>::value;

View File

@ -73,7 +73,7 @@ namespace sol {
else {
using ValueU = meta::unqualified_t<Value>;
// cannot get metatable: try regular table set?
if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_filter_v<ValueU>) {
if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_policy_v<ValueU>) {
// tag constructors so we don't get destroyed by lack of info
table_base_t::set(std::forward<Key>(key), detail::tagged<T, Value>(std::forward<Value>(value)));
}

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-05-21 06:26:29.108703 UTC
// This header was generated with sol v3.0.1-beta2 (revision 5dee45c)
// Generated 2019-05-21 07:55:59.916335 UTC
// This header was generated with sol v3.0.1-beta2 (revision ad1b966)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
@ -403,8 +403,8 @@ namespace sol {
struct as_args_t;
template <typename T>
struct protect_t;
template <typename F, typename... Filters>
struct filter_wrapper;
template <typename F, typename... Policies>
struct policy_wrapper;
template <typename T>
struct usertype_traits;

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-05-21 06:26:28.717749 UTC
// This header was generated with sol v3.0.1-beta2 (revision 5dee45c)
// Generated 2019-05-21 07:55:59.198915 UTC
// This header was generated with sol v3.0.1-beta2 (revision ad1b966)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -429,8 +429,8 @@ namespace sol {
struct as_args_t;
template <typename T>
struct protect_t;
template <typename F, typename... Filters>
struct filter_wrapper;
template <typename F, typename... Policies>
struct policy_wrapper;
template <typename T>
struct usertype_traits;
@ -6019,21 +6019,21 @@ namespace sol {
// end of sol/raii.hpp
// beginning of sol/filters.hpp
// beginning of sol/policies.hpp
namespace sol {
namespace detail {
struct filter_base_tag {};
struct policy_base_tag {};
} // namespace detail
template <int Target, int... In>
struct static_stack_dependencies : detail::filter_base_tag {};
struct static_stack_dependencies : detail::policy_base_tag {};
typedef static_stack_dependencies<-1, 1> self_dependency;
template <int... In>
struct returns_self_with : detail::filter_base_tag {};
struct returns_self_with : detail::policy_base_tag {};
typedef returns_self_with<> returns_self;
struct stack_dependencies : detail::filter_base_tag {
struct stack_dependencies : detail::policy_base_tag {
int target;
std::array<int, 64> stack_indices;
std::size_t len;
@ -6058,39 +6058,39 @@ namespace sol {
}
};
template <typename F, typename... Filters>
struct filter_wrapper {
typedef std::index_sequence_for<Filters...> indices;
template <typename F, typename... Policies>
struct policy_wrapper {
typedef std::index_sequence_for<Policies...> indices;
F value;
std::tuple<Filters...> filters;
std::tuple<Policies...> policies;
template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, filter_wrapper>>> = meta::enabler>
filter_wrapper(Fx&& fx, Args&&... args)
: value(std::forward<Fx>(fx)), filters(std::forward<Args>(args)...) {
template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, policy_wrapper>>> = meta::enabler>
policy_wrapper(Fx&& fx, Args&&... args)
: value(std::forward<Fx>(fx)), policies(std::forward<Args>(args)...) {
}
filter_wrapper(const filter_wrapper&) = default;
filter_wrapper& operator=(const filter_wrapper&) = default;
filter_wrapper(filter_wrapper&&) = default;
filter_wrapper& operator=(filter_wrapper&&) = default;
policy_wrapper(const policy_wrapper&) = default;
policy_wrapper& operator=(const policy_wrapper&) = default;
policy_wrapper(policy_wrapper&&) = default;
policy_wrapper& operator=(policy_wrapper&&) = default;
};
template <typename F, typename... Args>
auto filters(F&& f, Args&&... args) {
return filter_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...);
auto policies(F&& f, Args&&... args) {
return policy_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...);
}
namespace detail {
template <typename T>
using is_filter = meta::is_specialization_of<T, filter_wrapper>;
using is_policy = meta::is_specialization_of<T, policy_wrapper>;
template <typename T>
inline constexpr bool is_filter_v = is_filter<T>::value;
inline constexpr bool is_policy_v = is_policy<T>::value;
}
} // namespace sol
// end of sol/filters.hpp
// end of sol/policies.hpp
// beginning of sol/ebco.hpp
@ -7516,8 +7516,8 @@ namespace sol {
template <typename T>
struct is_constructor<protect_t<T>> : is_constructor<meta::unqualified_t<T>> {};
template <typename F, typename... Filters>
struct is_constructor<filter_wrapper<F, Filters...>> : is_constructor<meta::unqualified_t<F>> {};
template <typename F, typename... Policies>
struct is_constructor<policy_wrapper<F, Policies...>> : is_constructor<meta::unqualified_t<F>> {};
template <typename T>
inline constexpr bool is_constructor_v = is_constructor<T>::value;
@ -15856,9 +15856,9 @@ namespace sol {
} // namespace u_detail
namespace filter_detail {
namespace policy_detail {
template <int I, int... In>
inline void handle_filter(static_stack_dependencies<I, In...>, lua_State* L, int&) {
inline void handle_policy(static_stack_dependencies<I, In...>, lua_State* L, int&) {
if constexpr (sizeof...(In) == 0) {
(void)L;
return;
@ -15884,12 +15884,12 @@ namespace sol {
}
template <int... In>
inline void handle_filter(returns_self_with<In...>, lua_State* L, int& pushed) {
inline void handle_policy(returns_self_with<In...>, lua_State* L, int& pushed) {
pushed = stack::push(L, raw_index(1));
handle_filter(static_stack_dependencies<-1, In...>(), L, pushed);
handle_policy(static_stack_dependencies<-1, In...>(), L, pushed);
}
inline void handle_filter(const stack_dependencies& sdeps, lua_State* L, int&) {
inline void handle_policy(const stack_dependencies& sdeps, lua_State* L, int&) {
absolute_index ai(L, sdeps.target);
if (type_of(L, ai) != type::userdata) {
return;
@ -15906,11 +15906,11 @@ namespace sol {
lua_setuservalue(L, ai);
}
template <typename P, meta::disable<std::is_base_of<detail::filter_base_tag, meta::unqualified_t<P>>> = meta::enabler>
inline void handle_filter(P&& p, lua_State* L, int& pushed) {
template <typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler>
inline void handle_policy(P&& p, lua_State* L, int& pushed) {
pushed = std::forward<P>(p)(L, pushed);
}
} // namespace filter_detail
} // namespace policy_detail
namespace function_detail {
inline int no_construction_error(lua_State* L) {
@ -16626,14 +16626,14 @@ namespace sol {
}
};
template <typename T, typename F, typename... Filters, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, filter_wrapper<F, Filters...>, is_index, is_variable, checked, boost, clean_stack, C> {
typedef filter_wrapper<F, Filters...> P;
template <typename T, typename F, typename... Policies, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, policy_wrapper<F, Policies...>, is_index, is_variable, checked, boost, clean_stack, C> {
typedef policy_wrapper<F, Policies...> P;
template <std::size_t... In>
static int call(std::index_sequence<In...>, lua_State* L, P& fx) {
int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C>{}.call(L, fx.value);
(void)detail::swallow{ int(), (filter_detail::handle_filter(std::get<In>(fx.filters), L, pushed), int())... };
(void)detail::swallow{ int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... };
return pushed;
}
@ -16707,8 +16707,8 @@ namespace sol {
template <typename T>
struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> {};
template <typename F, typename... Filters>
struct is_var_bind<filter_wrapper<F, Filters...>> : is_var_bind<meta::unqualified_t<F>> {};
template <typename F, typename... Policies>
struct is_var_bind<policy_wrapper<F, Policies...>> : is_var_bind<meta::unqualified_t<F>> {};
} // namespace call_detail
template <typename T>
@ -17916,9 +17916,9 @@ namespace sol {
}
};
template <typename F, typename... Filters>
struct unqualified_pusher<filter_wrapper<F, Filters...>> {
using P = filter_wrapper<F, Filters...>;
template <typename F, typename... Policies>
struct unqualified_pusher<policy_wrapper<F, Policies...>> {
using P = policy_wrapper<F, Policies...>;
static int push(lua_State* L, const P& p) {
lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
@ -17937,9 +17937,9 @@ namespace sol {
}
};
template <typename T, typename F, typename... Filters>
struct unqualified_pusher<detail::tagged<T, filter_wrapper<F, Filters...>>> {
using P = filter_wrapper<F, Filters...>;
template <typename T, typename F, typename... Policies>
struct unqualified_pusher<detail::tagged<T, policy_wrapper<F, Policies...>>> {
using P = policy_wrapper<F, Policies...>;
using Tagged = detail::tagged<T, P>;
static int push(lua_State* L, const Tagged& p) {
@ -22806,7 +22806,7 @@ namespace sol {
constexpr static bool global = top_level && (meta::count_for_to_pack_v<1, meta::is_c_str, meta::unqualified_t<Keys>...> > 0);
auto pp = stack::push_pop<global>(*this);
lua_State* L = base_t::lua_state();
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...);
return *this;
}
@ -23198,7 +23198,7 @@ namespace sol {
else {
using ValueU = meta::unqualified_t<Value>;
// cannot get metatable: try regular table set?
if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_filter_v<ValueU>) {
if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_policy_v<ValueU>) {
// tag constructors so we don't get destroyed by lack of info
table_base_t::set(std::forward<Key>(key), detail::tagged<T, Value>(std::forward<Value>(value)));
}

View File

@ -23,4 +23,4 @@
#include "sol_defines.hpp"
#include <sol/filters.hpp>
#include <sol/policies.hpp>

View File

@ -28,7 +28,7 @@
#include <iostream>
#include <string>
TEST_CASE("filters/self", "ensure we return a direct reference to the lua userdata rather than creating a new one") {
TEST_CASE("policies/self", "ensure we return a direct reference to the lua userdata rather than creating a new one") {
struct vec2 {
float x = 20.f;
float y = 20.f;
@ -55,7 +55,7 @@ TEST_CASE("filters/self", "ensure we return a direct reference to the lua userda
lua.new_usertype<vec2>("vec2",
"x", &vec2::x,
"y", &vec2::y,
"normalize", sol::filters(&vec2::normalize, sol::returns_self()));
"normalize", sol::policies(&vec2::normalize, sol::returns_self()));
auto result1 = lua.safe_script(R"(
v1 = vec2.new()
@ -72,7 +72,7 @@ print(v2) -- v2 points to same, is not destroyed
REQUIRE(result1.valid());
}
TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance alive by attaching it to the lifetime of another userdata") {
TEST_CASE("policies/self_dependency", "ensure we can keep a userdata instance alive by attaching it to the lifetime of another userdata") {
struct dep;
struct gc_test;
static std::vector<dep*> deps_destroyed;
@ -108,7 +108,7 @@ TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance ali
return "{ " + std::to_string(d.value) + " }";
});
lua.new_usertype<gc_test>("gc_test",
"d", sol::filters(&gc_test::d, sol::self_dependency()),
"d", sol::policies(&gc_test::d, sol::self_dependency()),
sol::meta_function::to_string, [](gc_test& g) {
return "{ d: { " + std::to_string(g.d.value) + " } }";
});
@ -150,7 +150,7 @@ collectgarbage()
REQUIRE(gc_tests_destroyed[0] == g);
}
TEST_CASE("filters/stack_dependencies", "ensure we can take dependencies even to arguments pushed on the stack") {
TEST_CASE("policies/stack_dependencies", "ensure we can take dependencies even to arguments pushed on the stack") {
struct holder;
struct depends_on_reference;
struct composition_related;
@ -198,7 +198,7 @@ TEST_CASE("filters/stack_dependencies", "ensure we can take dependencies even to
lua.new_usertype<holder>("holder",
"value", &holder::value);
lua.new_usertype<depends_on_reference>("depends_on_reference",
"new", sol::filters(sol::constructors<depends_on_reference(holder&)>(), sol::stack_dependencies(-1, 1)),
"new", sol::policies(sol::constructors<depends_on_reference(holder&)>(), sol::stack_dependencies(-1, 1)),
"comp", &depends_on_reference::comp);
auto result1 = lua.safe_script(R"(
@ -255,10 +255,10 @@ int always_return_24(lua_State* L, int) {
return sol::stack::push(L, 24);
}
TEST_CASE("filters/custom", "ensure we can return dependencies on multiple things in the stack") {
TEST_CASE("policies/custom", "ensure we can return dependencies on multiple things in the stack") {
sol::state lua;
lua.set_function("f", sol::filters([]() { return std::string("hi there"); }, always_return_24));
lua.set_function("f", sol::policies([]() { return std::string("hi there"); }, always_return_24));
int value = lua["f"]();
REQUIRE(value == 24);