🎨 Refactor tutorial examples

- 🛠 Make sure the tutorials compile across platforms!
- ✍ Redo quite a bit of the documentation
This commit is contained in:
ThePhD 2021-03-06 10:14:48 -05:00
parent 8618e39486
commit 57d9a05f88
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
460 changed files with 2468 additions and 1476 deletions

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

7
.gitignore vendored
View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -46,6 +46,10 @@ x86/
# VSCode
.vscode/
# scratch space
main.cpp
scratch/
# CMake
build/
build-sol2/
@ -109,7 +113,6 @@ desktop.ini
# Miscellaneous
external/
scratch/
vendor/
.idea/
cmake-build-debug/

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # # sol3
# # # # sol2
# # # Required minimum version statement
cmake_minimum_required(VERSION 3.15.0)
@ -311,4 +311,11 @@ if (SOL2_IS_TOP_LEVEL AND (SOL2_DO_TESTS OR SOL2_DO_EXAMPLES))
message(STATUS "sol2 adding tests...")
add_subdirectory(tests "${CMAKE_BINARY_DIR}/tests")
endif()
# # # Scratch Space
# # Scratch space for diagnosing bugs and other shenanigans
if (SOL2_SCRATCH)
message(STATUS "sol2 adding scratch space...")
add_subdirectory(scratch)
endif()
endif()

View File

@ -1,6 +1,6 @@
# 🎉 Donators! ♥ 🎉
Thank you to all patrons, donators and contributors who help keep sol3 amazing.
Thank you to all patrons, donators and contributors who help keep sol2 amazing.
- Robert Salvet
- Ορφέας Ζαφείρης - 2x Donations!
@ -12,7 +12,7 @@ Thank you to all patrons, donators and contributors who help keep sol3 amazing.
# 🎉 Patrons! ♥ 🎉
Beyond just a one-time donation, patrons make a continued commitment to help keep sol3 supported and bug-free. Thank you for your patronage! Here are the supporters that wanted to be featured as sol3 contributors.
Beyond just a one-time donation, patrons make a continued commitment to help keep sol2 supported and bug-free. Thank you for your patronage! Here are the supporters that wanted to be featured as sol2 contributors.
- Joel Falcou
- Michael Caisse
@ -22,6 +22,6 @@ Beyond just a one-time donation, patrons make a continued commitment to help kee
# Company Patrons / Supporters #
Companies who sign up for a long-term support contract or patronage are listed here! They really push forward what's possible with sol3 (and the newer v3)! Please reach out to phdofthehouse@gmail.com if you are interested in a custom solution or a long-term support contract that goes beyond the current release's needs!
Companies who sign up for a long-term support contract or patronage are listed here! They really push forward what's possible with sol2 (and the newer v3)! Please reach out to phdofthehouse@gmail.com if you are interested in a custom solution or a long-term support contract that goes beyond the current release's needs!
- Intrepid Control Systems [intrepidcs.com](https://www.intrepidcs.com/)

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2017 Rapptz, ThePhD, and contributors

View File

@ -65,7 +65,7 @@ You can find [donation and sponorship options here](https://github.com/ThePhD/.g
# Features
- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol3 bar in graph).
- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol2 bar in graph).
- Supports retrieval and setting of multiple types including:
* `std::string`, `std::wstring`, `std::u16string` and `std::u32string` support (and for views).
* understands and works with containers such as `std::map/unordered_map`, c-style arrays, vectors, non-standard custom containers and more.
@ -98,7 +98,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.
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. If something doesn't work or you need special options, you may need to look into the different ways to support the project to have it done for you!
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. If something doesn't work or you need special options, you may need to look into the different ways to support the project to have it done for you!
@ -141,7 +141,7 @@ ThePhD
C++Now 2018 - Hudson Commons, Aspen Physics Center, Aspen, Colorado
[Deck](https://github.com/ThePhD/sol2/blob/develop/docs/presentations/2018.05.10%20-%20ThePhD%20-%20Compile%20Fast%2C%20Run%20Faster%2C%20Scale%20Forever.pdf)
"Scripting at the Speed of Thought: Using Lua in C++ with sol3"
"Scripting at the Speed of Thought: Using Lua in C++ with sol2"
ThePhD
CppCon 2018 - 404 Keystone, Meydenbauer Center, Aspen, Colorado
[Deck](https://github.com/ThePhD/sol2/blob/develop/docs/presentations/2018.09.28%20-%20ThePhD%20-%20Scripting%20at%20the%20Speed%20of%20Thought.pdf)

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,5 +1,5 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # # sol3, documentation generation
# # # # sol2, documentation generation
# # # Required minimum version statement
cmake_minimum_required(VERSION 3.15.0)

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors

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 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.
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.
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

@ -2,7 +2,7 @@ policies
========
*stack modification right before lua call returns*
``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:
``sol::policies`` 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 policies are defined for your use:
+------------------------------------+----------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| policy | usage | modification |

View File

@ -171,5 +171,5 @@ on function objects and proxies
.. note::
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>`.
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>`.

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 sol3. 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 sol2. 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 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`_.
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`_.
.. code-block:: cpp
:caption: function: check_usertype
@ -112,7 +112,7 @@ Directly attempts to rertieve the type ``T`` using sol3'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 sol3 usertype. Useful when you need to access sol3'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 sol2 usertype. Useful when you need to access sol2'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 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.
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.
.. code-block:: cpp
:caption: function: pop
@ -290,7 +290,7 @@ Note that you may
}
This extension point is to ``check`` a foreign userdata. It should return ``true`` if a type meets some custom userdata specifiction (from, say, another library or an internal framework), 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`_.
This extension point is to ``check`` a foreign userdata. It should return ``true`` if a type meets some custom userdata specifiction (from, say, another library or an internal framework), 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`_.
.. note::
@ -303,14 +303,14 @@ This extension point is to ``check`` a foreign userdata. It should return ``true
template <typename T>
std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
// implement custom getting here for non-sol3 userdatas:
// implement custom getting here for non-sol2 userdatas:
// if it doesn't match, return "false" and regular
// sol userdata getters will kick in
return { false, nullptr };
}
This extension point is to ``get`` a foreign userdata. It should return both ``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 default sol3 implementation take care of everything. You can use it to interop with other frameworks that are not sol3 but still include their power; e.g., for messing with ``kaguya`` or some other libraries. You can specialize it as shown in the `interop examples`_.
This extension point is to ``get`` a foreign userdata. It should return both ``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 default sol2 implementation take care of everything. You can use it to interop with other frameworks that are not sol2 but still include their power; e.g., for messing with ``kaguya`` or some other libraries. You can specialize it as shown in the `interop examples`_.
.. note::
@ -319,7 +319,7 @@ This extension point is to ``get`` a foreign userdata. It should return both ``t
.. 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 sol3-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 sol2-compatible way.)
.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction

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 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>`:
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>`:
.. code-block:: cpp
:linenos:

View File

@ -163,7 +163,7 @@ If you don't specify anything at all and the type is `destructible`_, then a des
usertype automatic (automagic) meta functions
+++++++++++++++++++++++++++++++++++++++++++++
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:
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:
* 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
@ -229,7 +229,7 @@ Otherwise, the following is used to specify functions to bind on the specific us
unregister
----------
You can unlink and kill a usertype and its associated functionality by calling ``.unregister()`` on a ``sol::usertype<T>`` or ``sol::metatable`` pointed at a proper sol3 metatable. This will entirely unlink and clean out sol3's internal lookup structures and key information.
You can unlink and kill a usertype and its associated functionality by calling ``.unregister()`` on a ``sol::usertype<T>`` or ``sol::metatable`` pointed at a proper sol2 metatable. This will entirely unlink and clean out sol2's internal lookup structures and key information.
runtime functions
-----------------

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. 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.
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.
.. 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 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.
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.
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 "sol3" entry)
* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`sol`_ is the "sol2" 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,10 +1,10 @@
build
=====
sol3 is a header-only library.
sol2 is a header-only library.
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.
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 also comes with a Meson Script. If things stop working, file a bug report.
sol2 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 sol3 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 sol2 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

@ -3,10 +3,46 @@ supported compilers, binary size, compile time
getting good final product out of sol
-------------------------------------
supported compilers
-------------------
GCC 7.x is now out alongside Visual Studio 2018. This means that `sol release v2.20.1`_ is the current version of the code targeted at the older compilers not listed below. Newer code will be targeted at working with the following compilers and leveraging their features, possibly taking advantage of whatever C++17 features are made available by the compilers and standard libraries bundled by-default with them.
Newer features will be targeted at the following compilers:
* VC++
- Visual Studio 2019, latest shipped compilers
- Visual Studio 2018, latest shipped compilers
* GCC (includes MinGW)
- v11.x
- v10.x
- v9.x
- v8.x
- v7.x
* Clang
- v11.x
- v10.x
- v9.x
- v8.x
- v7.x
- v6.x
- v5.x
- v4.x
- v3.9.x
Note that Visual Studio's 2018 Community Edition is absolutely free now, and installs faster and easier than ever before. It also removes a lot of hacky work arounds and formally supports decltype SFINAE.
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 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 `sol2 release v2.20.1`_: otherwise, always grab sol2's latest.
"I need older support"
++++++++++++++++++++++
GCC 7.x is now out alongside Visual Studio 2018. This means that `sol2 release v2.20.1`_ is the current version of the code targeted at the older compilers not listed above. Newer code will be targeted at C++17 and above.
``v2.20.1`` supports:
@ -26,36 +62,16 @@ 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 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.
If you need someone to, explicitly, backport some functionality or feature from a newer version that you like, then you can reach out to `these folks here <https://soasis.org/contact/opensource>`_.
Newer features will be targeted at the following compilers:
* VC++
- Visual Studio vNext
- Visual Studio 2018
* GCC (includes MinGW)
- v8.x
- v7.x
* Clang
- v7.x
- v6.x
- v5.x
- v4.x
- v3.9.x
Note that Visual Studio's 2018 Community Edition is absolutely free now, and installs faster and easier than ever before. It also removes a lot of hacky work arounds and formally supports decltype SFINAE.
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 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 sol3's latest.
feature support
---------------
track future compiler and feature support in `this issue here`_.
We support C++17. We have optional support for ``<variant>`` that is turned off by default for bad compilers like AppleClang with its missing implementation.
supported Lua version
---------------------
@ -69,11 +85,14 @@ We support:
* LuaJIT 2.1.x-beta3+
binary sizes
------------
For individiauls who use :doc:`usertypes<api/usertype>` a lot, they can find their compilation times increase. This is due to C++11 and C++14 not having very good facilities for handling template parameters and variadic template parameters. There are a few things in cutting-edge C++17 and C++Next that sol can use, but the problem is many people cannot work with the latest and greatest: therefore, we have to use older techniques that result in a fair amount of redundant function specializations that can be subject to the pickiness of the compiler's inlining and other such techniques.
compile speed improvemements
----------------------------
@ -87,6 +106,7 @@ Here are some notes on achieving better compile times without sacrificing too mu
* 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
----------
@ -95,6 +115,5 @@ The next step for sol from a developer standpoint is to formally make the librar
Hopefully, as things progress, we move things forward.
.. _sol release v2.20.1: https://github.com/ThePhD/sol2/releases/tag/v2.20.1
.. _sol2 release v2.20.1: https://github.com/ThePhD/sol2/releases/tag/v2.20.1
.. _issue describing preliminary steps can be found here: https://github.com/ThePhD/sol2/issues/436#issuecomment-312021508
.. _this issue here: https://github.com/ThePhD/sol2/issues/426

View File

@ -1,8 +1,8 @@
containers
==========
*working with containers in sol3*
*working with containers in sol2*
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 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 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
@ -28,7 +28,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, 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::usertype_container<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, 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::usertype_container<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:
@ -95,7 +95,7 @@ The various operations provided by ``usertype_container<T>`` are expected to be
container classifications
-------------------------
When you push a container into sol3, the default container handler deals with the containers by inspecting various properties, functions, and type definitions on them. Here are the broad implications of containers sol3's defaults will recognize, and which already-known containers fall into their categories:
When you push a container into sol2, the default container handler deals with the containers by inspecting various properties, functions, and type definitions on them. Here are the broad implications of containers sol2's defaults will recognize, and which already-known containers fall into their categories:
+------------------------+----------------------------------------+-------------------------+-----------------------------------------------------------------------------------------------+
| container type | requirements | known containers | notes/caveats |

View File

@ -64,7 +64,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 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.
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.
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.
@ -73,7 +73,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 sol3 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 sol2 to make this work out. You can read more :ref:`at the exception page here<exception-interop>`.
Catch and CRASH!
----------------
@ -82,7 +82,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 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.
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.
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.
@ -103,7 +103,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 sol3'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 sol2'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 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`_
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`_
.. 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 | Sol3 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra |
| | plain C | luawrapper | lua-intf | luabind | Selene | sol2 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra |
| | | | | | | | | | | | | | |
+===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+========+
| optional | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ |

View File

@ -1,13 +1,13 @@
functions
=========
*working with functions in sol3*
*working with functions in sol2*
There are a number of examples dealing with functions and how they can be bound to sol3:
There are a number of examples dealing with functions and how they can be bound to sol2:
* 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 sol3'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 sol2'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>`
@ -51,7 +51,7 @@ Furthermore, it is important to know that lambdas without a specified return typ
exception safety/handling
-------------------------
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.
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.
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.
@ -63,18 +63,18 @@ functions and argument passing
All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state<api/state>` or :doc:`sol::table<api/table>`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user.
You can change this behavior by defining ``SOL_FUNCTION_CALL_VALUE_SEMANTICS``, as defined in the :doc:`safety configuration page<safety>`. You can also change it for specific types using the ``sol::is_value_semantic_for_function<T>`` template and _partially specializing_ it to make either ``std::true_type``, ``std::false_type``, or equivalent ``true``/``false`` functionality.
You can change this behavior by defining ``SOL_FUNCTION_CALL_VALUE_SEMANTICS``, as defined in the :doc:`safety configuration page<safety>`. You can also change it for specific types using the ``sol::is_value_semantic_for_function<T>`` template and *partially specializing* it to make either ``std::true_type``, ``std::false_type``, or equivalent ``true``/``false`` functionality.
.. note::
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. 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.
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.
.. 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 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.
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.
.. note::

View File

@ -1,20 +1,16 @@
.. sol documentation master file, created by
sphinx-quickstart on Mon Feb 29 21:49:51 2016.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. image:: media/sol.png
:target: https://github.com/ThePhD/sol2
:alt: sol repository
:align: center
sol |version|
=============
sol2 (sol2, version |version|)
==============================
*a fast, simple C++ and Lua Binding*
When you need to hit the ground running with Lua and C++, `sol`_ is the go-to framework for high-performance binding with an easy to use API.
get going:
----------
@ -53,6 +49,8 @@ Come to the Github Issues! We've got a friendly community, and they can help you
|gh|
support
-------
@ -65,7 +63,8 @@ This is a time-consuming effort, so individuals who donate get to:
- steer the direction and time spent on sol
- get their name put up in the CONTRIBUTORS list
- put something of their choice on sol3's README or the documentation's front page
- put something of their choice on sol2's README or the documentation's front page
"I need feature X, maybe you have it?"
@ -73,6 +72,7 @@ This is a time-consuming effort, so individuals who donate get to:
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.
the basics:
-----------
@ -89,6 +89,8 @@ the basics:
:linenos:
Search
======
@ -101,33 +103,38 @@ Search
.. |pa| image:: media/become_a_patron_button.png
:height: 50
:target: https://www.patreon.com/soasis
:alt: sol3 Patreon
:alt: sol2 Patreon
:align: middle
.. |kf| image:: media/Ko-fi_Blue.png
:height: 50
:target: https://ko-fi.com/soasis
:alt: sol3 ko-fi
:alt: sol2 ko-fi
:align: middle
.. |lp| image:: media/liberapay_logo.png
:height: 50
:target: https://liberapay.com/Soasis
:alt: sol3 ko-fi
:alt: sol2 ko-fi
:align: middle
.. |pp| image:: media/pp_cc_mark_111x69.jpg
:height: 50
:target: https://www.paypal.me/Soasis
:alt: sol3 PayPal
:alt: sol2 PayPal
:align: middle
.. |gh| image:: media/github_logo.png
:height: 75
:target: https://github.com/ThePhD/sol2/issues
:alt: sol3 Github Issues Page
:alt: sol2 Github Issues Page
.. |gs| image:: media/github_sponsors_logo.png
:height: 55
:target: https://github.com/users/ThePhD/sponsorship
:alt: sol3 Sponsors Page
:alt: sol2 Sponsors Page
.. sol documentation master file, created by
sphinx-quickstart on Mon Feb 29 21:49:51 2016.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.

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 sol3 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 sol2 that I occasionally get pinged about:
`eevee`_ demonstrating the sheer code reduction by using sol3:
`eevee`_ demonstrating the sheer code reduction by using sol2:
.. |before| image:: media/eevee_code_before.jpg
@ -27,10 +27,10 @@ Okay, so the features don't convince you, the documentation doesn't convince you
* For Sandboxing `Fun`_!
* In `High Performance Computing research`_
- `Published research, too!`_
* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol3!
* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol2!
- `The pull request`_ in which it was introduced to the master branch.
* For scripting, in `OpenMPT`_
* (CppNow) sol3 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference!
* (CppNow) sol2 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`_
@ -39,27 +39,27 @@ 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 sol3"`_
- Eevee: `"I heartily recommend sol2"`_
- Elias Daler: `"sol2 is making usertypes in Lua so awesome <3"`_
- Racod's Lair: `"from outdated LuaBridge to superior #sol3"`_
- Racod's Lair: `"from outdated LuaBridge to superior #sol2"`_
* (Reddit) Posts on reddit about it!
- `sol2'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 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!
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!
.. _tell me about your uses!: https://github.com/ThePhD/sol2/issues/189
.. _eevee: https://twitter.com/eevee
.. _eevee's blog: https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/
.. _Fun: https://blog.rubenwardy.com/2020/07/26/sol3-script-sandbox/
.. _Fun: https://blog.rubenwardy.com/2020/07/26/sol2-script-sandbox/
.. _Jason Turner's presentation: https://github.com/lefticus/presentations/blob/master/WhyAndHowToAddScripting.md
.. _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 sol3": https://twitter.com/eevee/status/762040086540144644
.. _"from outdated LuaBridge to superior #sol3": https://twitter.com/racodslair/status/754031870640267264
.. _"I heartily recommend sol2": https://twitter.com/eevee/status/762040086540144644
.. _"from outdated LuaBridge to superior #sol2": https://twitter.com/racodslair/status/754031870640267264
.. _"sol2 is making usertypes in Lua so awesome <3": https://twitter.com/EliasDaler/status/778708299029946368
.. _sol2'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/

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 Sol3 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 sol2 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 sol3'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 sol2'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:
@ -69,7 +69,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 sol3 by default: only actual strings are allowed
- ``lua_tolstring`` conversions are not permitted on numbers through sol2 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
@ -179,7 +179,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. 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>`
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>`
functions
---------

View File

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

View File

@ -9,24 +9,22 @@ 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 `sol3 tutorial examples`_.
All of the code below is available at the `sol2 tutorial examples`_.
.. note::
Make sure to add ``SOL_ALL_SAFETIES_ON`` preprocessor define to your build configuration to turn safety on.
asserts / prerequisites
-----------------------
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:
Below, you will see use of a function called ``sol_c_assert``. This is an assert macro that comes with sol2 for the expression purpose of checking things; it's value is immaterial.
.. literalinclude:: ../../../include/sol/assert.hpp
:linenos:
:lines: 1-3, 19-
This is the assert used in the quick code below.
opening a state
---------------
@ -35,17 +33,21 @@ opening a state
:linenos:
.. _sol-state-on-lua-state:
using sol3 on a lua_State\*
using sol2 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 sol3 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 sol2 and nice things:
.. literalinclude:: ../../../examples/source/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp
:linenos:
.. _running-lua-code:
running lua code
@ -69,6 +71,7 @@ You can see more use of safety by employing the use of `.safe_script`_, which re
If you have the safety definitions on, `.script` will call into the `.safe_script` versions automatically. Otherwise, it will call into the `.unsafe_script` versions.
running lua code (low-level)
----------------------------
@ -81,11 +84,12 @@ You can use the individual load and function call operator to load, check, and t
.. literalinclude:: ../../../examples/source/tutorials/quick_n_dirty/running_lua_code_low_level.cpp
:linenos:
:lines: 1-10, 16-40, 47-49
:lines: 1-10, 16-40, 46-48
You can also `develop custom loaders`_ that pull from things that are not strings or files.
passing arguments to scripts
----------------------------
@ -95,6 +99,7 @@ Arguments to Lua scripts can be passed by first loading the file or script blob,
:linenos:
transferring functions (dumping bytecode)
-----------------------------------------
@ -104,6 +109,7 @@ You can dump the bytecode of a function, which allows you to transfer it to anot
:linenos:
set and get variables
---------------------
@ -144,6 +150,8 @@ You can erase things by setting it to ``nullptr`` or ``sol::lua_nil``.
Note that if its a :doc:`userdata/usertype<../api/usertype>` for a C++ type, the destructor will run only when the garbage collector deems it appropriate to destroy the memory. If you are relying on the destructor being run when its set to ``sol::lua_nil``, you're probably committing a mistake.
tables
------
@ -159,6 +167,8 @@ If you're going deep, be safe:
:linenos:
:lines: 35-
make tables
-----------
@ -179,6 +189,7 @@ You can put anything you want in tables as values or keys, including strings, nu
Note that this idea that things can be nested is important and will help later when you get into :ref:`namespacing<namespacing>`.
functions
---------
@ -205,6 +216,7 @@ The lua code to call these things is:
You can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it.
self call
---------
@ -215,6 +227,7 @@ You can pass the ``self`` argument through C++ to emulate 'member function' call
:lines: 1-
multiple returns from lua
-------------------------
@ -223,6 +236,7 @@ multiple returns from lua
:lines: 1-
multiple returns to lua
-----------------------
@ -231,6 +245,7 @@ multiple returns to lua
:lines: 1-
C++ classes from C++
--------------------
@ -248,7 +263,7 @@ Is set as a :doc:`userdata + usertype<../api/usertype>`.
.. literalinclude:: ../../../examples/source/tutorials/quick_n_dirty/userdata.cpp
:linenos:
:lines: 1-57,97-
:lines: 1-60,101-
``std::unique_ptr``/``std::shared_ptr``'s reference counts / deleters will :doc:`be respected<../api/unique_usertype_traits>`.
@ -265,12 +280,14 @@ You can retrieve the userdata in the same way as everything else. Importantly, n
:lines: 46-
C++ classes put into Lua
------------------------
See this :doc:`section here<cxx-in-lua>`. Also check out a `basic example`_, `special functions example`_ and `initializers example`_! There are many more examples that show off the usage of classes in C++, so please peruse them all carefully as it can be as simple or as complex as your needs are.
.. _namespacing:
namespacing
@ -285,6 +302,8 @@ You can emulate namespacing by having a table and giving it the namespace names
This technique can be used to register namespace-like functions and classes. It can be as deep as you want. Just make a table and name it appropriately, in either Lua script or using the equivalent sol code. As long as the table FIRST exists (e.g., make it using a script or with one of sol's methods or whatever you like), you can put anything you want specifically into that table using :doc:`sol::table's<../api/table>` abstractions.
there is a LOT more
-------------------
@ -308,4 +327,4 @@ Some more things you can do/read about:
.. _basic example: https://github.com/ThePhD/sol2/blob/develop/examples/source/usertype.cpp
.. _special functions example: https://github.com/ThePhD/sol2/blob/develop/examples/source/usertype_special_functions.cpp
.. _initializers example: https://github.com/ThePhD/sol2/blob/develop/examples/source/usertype_initializers.cpp
.. _sol3 tutorial examples: https://github.com/ThePhD/sol2/tree/develop/examples/source/tutorials/quick_n_dirty
.. _sol2 tutorial examples: https://github.com/ThePhD/sol2/tree/develop/examples/source/tutorials/quick_n_dirty

View File

@ -55,13 +55,13 @@ Notice here that we bind two separate functions. What if we wanted to bind only
This is useful for functions which can take multiple types and need to behave differently based on those types. You can set as many overloads as you want, and they can be of many different types.
..note::
.. note::
Binding functions with default parameters (``void func(int a = 1)``) does not magically bind multiple versions of the function to be called with the default parameters. You must instead use :doc:`sol::overload<../api/overload>` and bind the full version of the function, with lambdas or similar for the function calls one by one.
Binding functions with default parameters (``void func(int a = 1);``) does not magically bind multiple versions of the function to be called with the default parameters. You must instead use :doc:`sol::overload<../api/overload>` and bind the full version of the function, with lambdas or similar for the function calls one by one.
..note::
.. note::
please make sure to understand the :ref:`implications of binding a lambda/callable struct in the various ways<binding-callable-objects>` and what it means for your code!
please make sure to understand the :ref:`implications of binding a lambda/callable struct in the various ways <binding-callable-objects>` and what it means for your code!
Getting a function from Lua
@ -74,7 +74,7 @@ You can use them to retrieve callables from Lua and call the underlying function
.. literalinclude:: ../../../examples/source/tutorials/reading_functions.cpp
:language: cpp
:linenos:
:caption: Retrieving a sol::(unsafe_/protected_)function
:caption: Retrieving a sol::(unsafe\ _/protected\ _)function
:name: reading-functions
.. note::

View File

@ -1,7 +1,7 @@
usertypes
=========
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.
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.
To learn more about usertypes, visit:
@ -45,14 +45,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. sol3'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. sol2'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 sol3, 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 sol2, 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: 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)
- 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)
* 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.

110
examples/.clang-format Normal file
View File

@ -0,0 +1,110 @@
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
BasedOnStyle: WebKit
IndentWidth: 5
TabWidth: 5
ContinuationIndentWidth: 5
UseTab: ForIndentation
# Namespaces
NamespaceIndentation: All
CompactNamespaces: true
FixNamespaceComments: true
# Overall Alignment
ColumnLimit: 65
AlignAfterOpenBracket: DontAlign # uses ContinuationIndentWidth for this instead
AccessModifierOffset: -5 # do not push public: or private: around
#AlignConsecutiveAssignments: true # affects more than what's expected: do not use
#AlignConsecutiveDeclarations: true # affects more than what's expected: do not use
# Type Alignment
DerivePointerAlignment: false
PointerAlignment: Left
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true
# Comments
AlignTrailingComments: true
ReflowComments: true
# Macros
AlignEscapedNewlines: Left
#IndentPPDirectives: None
# Functions
AllowShortFunctionsOnASingleLine: None
AlwaysBreakAfterReturnType: None
BreakConstructorInitializers: BeforeComma
ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
BinPackArguments: false
BinPackParameters: true
# Classes
BreakBeforeInheritanceComma: false
# Braces
Cpp11BracedListStyle: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: false
AfterStruct: false
AfterControlStatement: false
AfterClass: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
BeforeElse: true
BeforeCatch: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
# Control Statements
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
IndentCaseLabels: false
# Spaces
SpaceAfterCStyleCast: false
SpacesInCStyleCastParentheses: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
MaxEmptyLinesToKeep: 3
# OCD
SortUsingDeclarations: true
SortIncludes: false
---
Language: Cpp
Standard: Cpp11

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 Examples
# # # sol2 Examples
if (SOL2_DYNAMIC_LOADING_EXAMPLES OR SOL2_DYNAMIC_LOADING_EXAMPLES_SINGLE OR SOL2_DYNAMIC_LOADING_EXAMPLES_SINGLE_GENERATED)
# # require_from_dll example

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 Customization Examples
# # # sol2 Customization Examples
function (MAKE_CUSTOMIZATION_EXAMPLE example_suffix target_sol)
set(customization_example_name customization_to_table${example_suffix})

View File

@ -10,10 +10,14 @@
#include <functional>
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index, std::function<sol::check_handler_type> handler, sol::stack::record& tracking);
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index,
std::function<sol::check_handler_type> handler,
sol::stack::record& tracking);
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L, int index, sol::stack::record& tracking);
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L,
int index, sol::stack::record& tracking);
int sol_lua_push(sol::types<zm::vec3>, lua_State* L, const zm::vec3& v);
int sol_lua_push(
sol::types<zm::vec3>, lua_State* L, const zm::vec3& v);
#endif // PROGRAM_LUA_ZM_INTEROP_HPP

View File

@ -17,8 +17,10 @@ namespace zm {
#pragma GCC diagnostic ignored "-Wpedantic"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
#pragma warning(disable : 4201) // nonstandard extension used :
// nameless struct/union
#pragma warning(disable : 4324) // structure was padded due to
// alignment specifier
#endif
union {
float elements[3];
@ -46,7 +48,8 @@ namespace zm {
vec3() : x(0), y(0), z(0) {
}
vec3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {
vec3(float x_, float y_, float z_)
: x(x_), y(y_), z(z_) {
}
constexpr float* data() {
@ -61,7 +64,8 @@ namespace zm {
return this->elements[i];
}
constexpr const float& operator[](std::size_t i) const {
constexpr const float& operator[](
std::size_t i) const {
return this->elements[i];
}
};

View File

@ -6,5 +6,8 @@
#include <sol/sol.hpp>
void register_lua(sol::state& lua) {
lua.new_usertype<entity>("entity", "position", sol::property(&entity::get_position, &entity::set_position));
lua.new_usertype<entity>("entity",
"position",
sol::property(
&entity::get_position, &entity::set_position));
}

View File

@ -5,24 +5,31 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index, std::function<sol::check_handler_type> handler, sol::stack::record& tracking) {
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index,
std::function<sol::check_handler_type> handler,
sol::stack::record& tracking) {
// use sol's method for checking
// specifically for a table
return sol::stack::check<sol::lua_table>(L, index, handler, tracking);
return sol::stack::check<sol::lua_table>(
L, index, handler, tracking);
}
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L, int index, sol::stack::record& tracking) {
sol::lua_table vec3table = sol::stack::get<sol::lua_table>(L, index, tracking);
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L,
int index, sol::stack::record& tracking) {
sol::lua_table vec3table
= sol::stack::get<sol::lua_table>(L, index, tracking);
float x = vec3table["x"];
float y = vec3table["y"];
float z = vec3table["z"];
return zm::vec3 { x, y, z };
}
int sol_lua_push(sol::types<zm::vec3>, lua_State* L, const zm::vec3& v) {
int sol_lua_push(
sol::types<zm::vec3>, lua_State* L, const zm::vec3& v) {
// create table
sol::state_view lua(L);
sol::table vec3table = sol::table::create_with(L, "x", v.x, "y", v.y, "z", v.z);
sol::table vec3table = sol::table::create_with(
L, "x", v.x, "y", v.y, "z", v.z);
// use base sol method to
// push the table
int amount = sol::stack::push(L, vec3table);

View File

@ -7,12 +7,14 @@
#include <iostream>
int main(int, char*[]) {
std::cout << "=== customization: vec3 as table ===" << std::endl;
std::cout << "=== customization: vec3 as table ==="
<< std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base);
std::cout << "registering entities into Lua ..." << std::endl;
std::cout << "registering entities into Lua ..."
<< std::endl;
register_lua(lua);
std::cout << "running script ..." << std::endl;
@ -29,7 +31,8 @@ print("new_pos", new_pos.x, new_pos.y, new_pos.z)
sol::optional<sol::error> result = lua.safe_script(script);
if (result.has_value()) {
std::cerr << "Something went horribly wrong: " << result.value().what() << std::endl;
std::cerr << "Something went horribly wrong: "
<< result.value().what() << std::endl;
}
std::cout << "finishing ..." << std::endl;

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 interop Examples - luabridge
# # # sol2 interop Examples - luabridge
find_package(LuaBridgeBuild)

View File

@ -1,5 +1,6 @@
#define SOL_ALL_SAFETIES_ON 1
#define SOL_ENABLE_INTEROP 1 // MUST be defined to use interop features
#define SOL_ENABLE_INTEROP \
1 // MUST be defined to use interop features
#include <sol/sol.hpp>
#include <LuaBridge/LuaBridge.h>
@ -28,7 +29,9 @@ private:
};
template <typename T, typename Handler>
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L,
int relindex, sol::type index_type, Handler&& handler,
sol::stack::record& tracking) {
// just marking unused parameters for no compiler warnings
(void)index_type;
(void)handler;
@ -39,10 +42,17 @@ inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol
}
template <typename T>
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t,
lua_State* L, int relindex, void* unadjusted_pointer,
sol::stack::record& tracking) {
(void)unadjusted_pointer;
int index = lua_absindex(L, relindex);
if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
if (!sol_lua_interop_check(t,
L,
index,
sol::type::userdata,
sol::no_panic,
tracking)) {
return { false, nullptr };
}
T* corrected = luabridge::Userdata::get<T>(L, index, true);
@ -53,15 +63,22 @@ void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view
// state_view is cheap to construct
sol::state_view lua(L);
// bind and set up your things: everything is entirely self-contained
// bind and set up your things: everything is entirely
// self-contained
lua["f"] = sol::overload(
[](A& from_luabridge) {
std::cout << "calling 1-argument version with luabridge-created A { " << from_luabridge.value() << " }" << std::endl;
std::cout << "calling 1-argument version with "
"luabridge-created A { "
<< from_luabridge.value() << " }"
<< std::endl;
sol_c_assert(from_luabridge.value() == 24);
},
[](A& from_luabridge, int second_arg) {
std::cout << "calling 2-argument version with luabridge-created A { " << from_luabridge.value() << " } and integer argument of " << second_arg
<< std::endl;
std::cout << "calling 2-argument version with "
"luabridge-created A { "
<< from_luabridge.value()
<< " } and integer argument of "
<< second_arg << std::endl;
sol_c_assert(from_luabridge.value() == 24);
sol_c_assert(second_arg == 5);
});
@ -76,8 +93,11 @@ void check_with_sol(lua_State* L) {
int main(int, char*[]) {
std::cout << "=== interop example (LuaBridge) ===" << std::endl;
std::cout << "code modified from LuaBridge's examples: https://github.com/vinniefalco/LuaBridge" << std::endl;
std::cout << "=== interop example (LuaBridge) ==="
<< std::endl;
std::cout << "code modified from LuaBridge's examples: "
"https://github.com/vinniefalco/LuaBridge"
<< std::endl;
struct closer {
void operator()(lua_State* L) {

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 interop Examples - kaguya
# # # sol2 interop Examples - kaguya
find_package(KaguyaBuild)

View File

@ -1,5 +1,6 @@
#define SOL_ALL_SAFETIES_ON 1
#define SOL_ENABLE_INTEROP 1 // MUST be defined to use interop features
#define SOL_ENABLE_INTEROP \
1 // MUST be defined to use interop features
#include <sol/sol.hpp>
#include <iostream>
@ -8,8 +9,8 @@
// written by satoren:
// https://github.com/satoren/kaguya
// Copyright satoren
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
struct ABC {
@ -35,34 +36,41 @@ private:
};
template <typename T, typename Handler>
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L,
int relindex, sol::type index_type, Handler&& handler,
sol::stack::record& tracking) {
// just marking unused parameters for no compiler warnings
(void)index_type;
(void)handler;
// using 1 element
tracking.use(1);
int index = lua_absindex(L, relindex);
// use kaguya's own detail wrapper check to see if it's correct
bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index);
// use kaguya's own detail wrapper check to see if it's
// correct
bool is_correct_type
= kaguya::detail::object_wrapper_type_check(L, index);
return is_correct_type;
}
template <typename T>
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T>, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T>,
lua_State* L, int relindex, void* unadjusted_pointer,
sol::stack::record& tracking) {
// you may not need to specialize this method every time:
// some libraries are compatible with sol2's layout
// kaguya's storage of data is incompatible with sol's
// it stores the data directly in the pointer, not a pointer inside of the `void*`
// therefore, leave the raw userdata pointer as-is,
// if it's of the right type
// it stores the data directly in the pointer, not a pointer
// inside of the `void*` therefore, leave the raw userdata
// pointer as-is, if it's of the right type
int index = lua_absindex(L, relindex);
if (!kaguya::detail::object_wrapper_type_check(L, index)) {
return { false, nullptr };
}
// using 1 element
tracking.use(1);
kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
kaguya::ObjectWrapperBase* base
= kaguya::object_wrapper(L, index);
return { true, static_cast<T*>(base->get()) };
}
@ -70,15 +78,22 @@ void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view
// state_view is cheap to construct
sol::state_view lua(L);
// bind and set up your things: everything is entirely self-contained
// bind and set up your things: everything is entirely
// self-contained
lua["f"] = sol::overload(
[](ABC& from_kaguya) {
std::cout << "calling 1-argument version with kaguya-created ABC { " << from_kaguya.value() << " }" << std::endl;
std::cout << "calling 1-argument version with "
"kaguya-created ABC { "
<< from_kaguya.value() << " }"
<< std::endl;
sol_c_assert(from_kaguya.value() == 24);
},
[](ABC& from_kaguya, int second_arg) {
std::cout << "calling 2-argument version with kaguya-created ABC { " << from_kaguya.value() << " } and integer argument of " << second_arg
<< std::endl;
std::cout << "calling 2-argument version with "
"kaguya-created ABC { "
<< from_kaguya.value()
<< " } and integer argument of "
<< second_arg << std::endl;
sol_c_assert(from_kaguya.value() == 24);
sol_c_assert(second_arg == 5);
});
@ -93,17 +108,23 @@ void check_with_sol(lua_State* L) {
int main(int, char*[]) {
std::cout << "=== interop example (kaguya) ===" << std::endl;
std::cout << "(code lifted from kaguya's README examples: https://github.com/satoren/kaguya)" << std::endl;
std::cout << "=== interop example (kaguya) ==="
<< std::endl;
std::cout << "(code lifted from kaguya's README examples: "
"https://github.com/satoren/kaguya)"
<< std::endl;
kaguya::State state;
state["ABC"].setClass(kaguya::UserdataMetatable<ABC>()
.setConstructors<ABC(), ABC(int)>()
.addFunction("get_value", &ABC::value)
.addFunction("set_value", &ABC::setValue)
.addOverloadedFunctions("overload", &ABC::overload1, &ABC::overload2)
.addStaticFunction("nonmemberfun", [](ABC* self, int) { return 1; }));
state["ABC"].setClass(
kaguya::UserdataMetatable<ABC>()
.setConstructors<ABC(), ABC(int)>()
.addFunction("get_value", &ABC::value)
.addFunction("set_value", &ABC::setValue)
.addOverloadedFunctions(
"overload", &ABC::overload1, &ABC::overload2)
.addStaticFunction("nonmemberfun",
[](ABC* self, int) { return 1; }));
register_sol_stuff(state.state());

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 interop Examples - luwra
# # # sol2 interop Examples - luwra
find_package(LuwraBuild)

View File

@ -1,5 +1,6 @@
#define SOL_ALL_SAFETIES_ON 1
#define SOL_ENABLE_INTEROP 1 // MUST be defined to use interop features
#define SOL_ENABLE_INTEROP \
1 // MUST be defined to use interop features
#include <sol/sol.hpp>
#include <luwra.hpp>
@ -33,7 +34,9 @@ private:
};
template <typename T, typename Handler>
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L,
int relindex, sol::type index_type, Handler&& handler,
sol::stack::record& tracking) {
// just marking unused parameters for no compiler warnings
(void)index_type;
(void)handler;
@ -41,7 +44,8 @@ inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol
tracking.use(1);
int index = lua_absindex(L, relindex);
if (lua_getmetatable(L, index) == 1) {
luaL_getmetatable(L, luwra::internal::UserTypeReg<T>::name.c_str());
luaL_getmetatable(
L, luwra::internal::UserTypeReg<T>::name.c_str());
bool is_correct_type = lua_rawequal(L, -2, -1) == 1;
lua_pop(L, 2);
return is_correct_type;
@ -50,11 +54,18 @@ inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol
}
template <typename T>
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t,
lua_State* L, int relindex, void* unadjusted_pointer,
sol::stack::record& tracking) {
// you may not need to specialize this method every time:
// some libraries are compatible with sol3's layout
// some libraries are compatible with sol2's layout
int index = lua_absindex(L, relindex);
if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
if (!sol_lua_interop_check(t,
L,
index,
sol::type::userdata,
sol::no_panic,
tracking)) {
return { false, nullptr };
}
return { true, static_cast<T*>(unadjusted_pointer) };
@ -64,15 +75,22 @@ void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view
// state_view is cheap to construct
sol::state_view lua(L);
// bind and set up your things: everything is entirely self-contained
// bind and set up your things: everything is entirely
// self-contained
lua["f"] = sol::overload(
[](ABC& from_luwra) {
std::cout << "calling 1-argument version with luwra-created ABC { " << from_luwra.value() << " }" << std::endl;
std::cout << "calling 1-argument version with "
"luwra-created ABC { "
<< from_luwra.value() << " }"
<< std::endl;
sol_c_assert(from_luwra.value() == 24);
},
[](ABC& from_luwra, int second_arg) {
std::cout << "calling 2-argument version with luwra-created ABC { " << from_luwra.value() << " } and integer argument of " << second_arg
<< std::endl;
std::cout << "calling 2-argument version with "
"luwra-created ABC { "
<< from_luwra.value()
<< " } and integer argument of "
<< second_arg << std::endl;
sol_c_assert(from_luwra.value() == 24);
sol_c_assert(second_arg == 5);
});
@ -88,11 +106,16 @@ void check_with_sol(lua_State* L) {
int main(int, char*[]) {
std::cout << "=== interop example (luwra) ===" << std::endl;
std::cout << "code modified from luwra's documentation examples: https://github.com/vapourismo/luwra" << std::endl;
std::cout << "code modified from luwra's documentation "
"examples: https://github.com/vapourismo/luwra"
<< std::endl;
luwra::StateWrapper state;
state.registerUserType<ABC(int)>("ABC", { LUWRA_MEMBER(ABC, value), LUWRA_MEMBER(ABC, setValue) }, {});
state.registerUserType<ABC(int)>("ABC",
{ LUWRA_MEMBER(ABC, value),
LUWRA_MEMBER(ABC, setValue) },
{});
register_sol_stuff(state);

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 interop Examples - tolua
# # # sol2 interop Examples - tolua
find_package(ToLuappBuild REQUIRED)

View File

@ -6,8 +6,7 @@ private:
int m_health;
public:
Player()
: m_health(0) {
Player() : m_health(0) {
}
void setHealth(int health) {
m_health = health;

View File

@ -1,5 +1,6 @@
#define SOL_ALL_SAFETIES_ON 1
#define SOL_ENABLE_INTEROP 1 // MUST be defined to use interop features
#define SOL_ENABLE_INTEROP \
1 // MUST be defined to use interop features
#include <sol/sol.hpp>
#include "Player.h"
@ -18,10 +19,12 @@
/* NOTE: there is no sol_lua_interop_get here,
because tolua types are -- thankfully -- memory-compatible
in most cases with sol.
Please check other examples like kaguya or LuaBribe for an example
of how to also write the getter for your type*/
Please check other examples like kaguya or LuaBribe for an
example of how to also write the getter for your type*/
template <typename T, typename Handler>
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L,
int relindex, sol::type index_type, Handler&& handler,
sol::stack::record& tracking) {
tracking.use(1);
// just marking unused parameters for no compiler warnings
(void)index_type;
@ -29,7 +32,8 @@ inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol
int index = lua_absindex(L, relindex);
std::string name = sol::detail::short_demangle<T>();
tolua_Error tolua_err {};
int r = tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
int r = tolua_isusertype(
L, index, name.c_str(), 0, &tolua_err);
if (r == 0) {
// tolua seems to leave garbage on the stack
// when the check fails
@ -44,14 +48,21 @@ void register_sol_stuff(lua_State* L) {
// grab raw state and put into state_view
// state_view is cheap to construct
sol::state_view lua(L);
// bind and set up your things: everything is entirely self-contained
// bind and set up your things: everything is entirely
// self-contained
lua["f"] = sol::overload(
[](Player& from_tolua) {
std::cout << "calling 1-argument version with tolua-created Player { health:" << from_tolua.getHealth() << " }" << std::endl;
std::cout << "calling 1-argument version with "
"tolua-created Player { health:"
<< from_tolua.getHealth() << " }"
<< std::endl;
sol_c_assert(from_tolua.getHealth() == 4);
},
[](Player& from_tolua, int second_arg) {
std::cout << "calling 2-argument version with tolua-created Player { health: " << from_tolua.getHealth() << " } and integer argument of "
std::cout << "calling 2-argument version with "
"tolua-created Player { health: "
<< from_tolua.getHealth()
<< " } and integer argument of "
<< second_arg << std::endl;
sol_c_assert(from_tolua.getHealth() == 4);
sol_c_assert(second_arg == 5);
@ -68,13 +79,18 @@ void check_with_sol(lua_State* L) {
int main(int, char*[]) {
std::cout << "=== interop example (tolua) ===" << std::endl;
std::cout << "(code lifted from a sol2 user's use case: https://github.com/ThePhD/sol2/issues/511#issuecomment-331729884)" << std::endl;
std::cout << "(code lifted from a sol2 user's use case: "
"https://github.com/ThePhD/sol2/issues/"
"511#issuecomment-331729884)"
<< std::endl;
lua_State* L = luaL_newstate();
luaL_openlibs(L); // initalize all lua standard library functions
tolua_open(L); // initalize tolua
tolua_Player_open(L); // make Player class accessible from LUA
luaL_openlibs(
L); // initalize all lua standard library functions
tolua_open(L); // initalize tolua
tolua_Player_open(
L); // make Player class accessible from LUA
register_sol_stuff(L);

View File

@ -1,6 +1,7 @@
/*
** Lua binding: Player
** Generated automatically by tolua++-1.0.93-lua53 on Sat Feb 10 08:48:53 2018.
** Generated automatically by tolua++-1.0.93-lua53 on Sat Feb 10
*08:48:53 2018.
*/
#ifndef __cplusplus
@ -11,16 +12,15 @@
#include "tolua++.h"
/* Exported function */
TOLUA_API int tolua_Player_open (lua_State* tolua_S);
TOLUA_API int tolua_Player_open(lua_State* tolua_S);
#include "Player.h"
/* function to release collected object via destructor */
#ifdef __cplusplus
static int tolua_collect_Player (lua_State* tolua_S)
{
Player* self = (Player*) tolua_tousertype(tolua_S,1,0);
static int tolua_collect_Player(lua_State* tolua_S) {
Player* self = (Player*)tolua_tousertype(tolua_S, 1, 0);
Mtolua_delete(self);
return 0;
}
@ -28,190 +28,199 @@ static int tolua_collect_Player (lua_State* tolua_S)
/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"Player");
static void tolua_reg_types(lua_State* tolua_S) {
tolua_usertype(tolua_S, "Player");
}
/* method: new of class Player */
#ifndef TOLUA_DISABLE_tolua_Player_Player_new00
static int tolua_Player_Player_new00(lua_State* tolua_S)
{
static int tolua_Player_Player_new00(lua_State* tolua_S) {
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"Player",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
tolua_Error tolua_err;
if (!tolua_isusertable(tolua_S, 1, "Player", 0, &tolua_err)
|| !tolua_isnoobj(tolua_S, 2, &tolua_err))
goto tolua_lerror;
else
#endif
{
{
Player* tolua_ret = (Player*) Mtolua_new((Player)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"Player");
}
}
return 1;
{
{
Player* tolua_ret
= (Player*)Mtolua_new((Player)());
tolua_pushusertype(
tolua_S, (void*)tolua_ret, "Player");
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
return 0;
tolua_lerror:
tolua_error(
tolua_S, "#ferror in function 'new'.", &tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: new_local of class Player */
#ifndef TOLUA_DISABLE_tolua_Player_Player_new00_local
static int tolua_Player_Player_new00_local(lua_State* tolua_S)
{
static int tolua_Player_Player_new00_local(lua_State* tolua_S) {
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"Player",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
tolua_Error tolua_err;
if (!tolua_isusertable(tolua_S, 1, "Player", 0, &tolua_err)
|| !tolua_isnoobj(tolua_S, 2, &tolua_err))
goto tolua_lerror;
else
#endif
{
{
Player* tolua_ret = (Player*) Mtolua_new((Player)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"Player");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
}
}
return 1;
{
{
Player* tolua_ret
= (Player*)Mtolua_new((Player)());
tolua_pushusertype(
tolua_S, (void*)tolua_ret, "Player");
tolua_register_gc(tolua_S, lua_gettop(tolua_S));
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
return 0;
tolua_lerror:
tolua_error(
tolua_S, "#ferror in function 'new'.", &tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: delete of class Player */
#ifndef TOLUA_DISABLE_tolua_Player_Player_delete00
static int tolua_Player_Player_delete00(lua_State* tolua_S)
{
static int tolua_Player_Player_delete00(lua_State* tolua_S) {
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"Player",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
tolua_Error tolua_err;
if (!tolua_isusertype(tolua_S, 1, "Player", 0, &tolua_err)
|| !tolua_isnoobj(tolua_S, 2, &tolua_err))
goto tolua_lerror;
else
#endif
{
Player* self = (Player*) tolua_tousertype(tolua_S,1,0);
{
Player* self
= (Player*)tolua_tousertype(tolua_S, 1, 0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'delete'", NULL);
if (!self)
tolua_error(tolua_S,
"invalid 'self' in function 'delete'",
NULL);
#endif
Mtolua_delete(self);
}
return 0;
Mtolua_delete(self);
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'delete'.",&tolua_err);
return 0;
tolua_lerror:
tolua_error(
tolua_S, "#ferror in function 'delete'.", &tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: setHealth of class Player */
#ifndef TOLUA_DISABLE_tolua_Player_Player_setHealth00
static int tolua_Player_Player_setHealth00(lua_State* tolua_S)
{
static int tolua_Player_Player_setHealth00(lua_State* tolua_S) {
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"Player",0,&tolua_err) ||
!tolua_isnumber(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
tolua_Error tolua_err;
if (!tolua_isusertype(tolua_S, 1, "Player", 0, &tolua_err)
|| !tolua_isnumber(tolua_S, 2, 0, &tolua_err)
|| !tolua_isnoobj(tolua_S, 3, &tolua_err))
goto tolua_lerror;
else
#endif
{
Player* self = (Player*) tolua_tousertype(tolua_S,1,0);
int _health = ((int) tolua_tonumber(tolua_S,2,0));
{
Player* self
= (Player*)tolua_tousertype(tolua_S, 1, 0);
int _health = ((int)tolua_tonumber(tolua_S, 2, 0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'setHealth'", NULL);
if (!self)
tolua_error(tolua_S,
"invalid 'self' in function 'setHealth'",
NULL);
#endif
{
self->setHealth(_health);
}
}
return 0;
{ self->setHealth(_health); }
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'setHealth'.",&tolua_err);
return 0;
tolua_lerror:
tolua_error(tolua_S,
"#ferror in function 'setHealth'.",
&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: getHealth of class Player */
#ifndef TOLUA_DISABLE_tolua_Player_Player_getHealth00
static int tolua_Player_Player_getHealth00(lua_State* tolua_S)
{
static int tolua_Player_Player_getHealth00(lua_State* tolua_S) {
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"Player",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
tolua_Error tolua_err;
if (!tolua_isusertype(tolua_S, 1, "Player", 0, &tolua_err)
|| !tolua_isnoobj(tolua_S, 2, &tolua_err))
goto tolua_lerror;
else
#endif
{
Player* self = (Player*) tolua_tousertype(tolua_S,1,0);
{
Player* self
= (Player*)tolua_tousertype(tolua_S, 1, 0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'getHealth'", NULL);
if (!self)
tolua_error(tolua_S,
"invalid 'self' in function 'getHealth'",
NULL);
#endif
{
int tolua_ret = (int) self->getHealth();
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
}
}
return 1;
{
int tolua_ret = (int)self->getHealth();
tolua_pushnumber(tolua_S, (lua_Number)tolua_ret);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'getHealth'.",&tolua_err);
return 0;
tolua_lerror:
tolua_error(tolua_S,
"#ferror in function 'getHealth'.",
&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* Open function */
TOLUA_API int tolua_Player_open (lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S,NULL,0);
tolua_beginmodule(tolua_S,NULL);
#ifdef __cplusplus
tolua_cclass(tolua_S,"Player","Player","",tolua_collect_Player);
#else
tolua_cclass(tolua_S,"Player","Player","",NULL);
#endif
tolua_beginmodule(tolua_S,"Player");
tolua_function(tolua_S,"new",tolua_Player_Player_new00);
tolua_function(tolua_S,"new_local",tolua_Player_Player_new00_local);
tolua_function(tolua_S,".call",tolua_Player_Player_new00_local);
tolua_function(tolua_S,"delete",tolua_Player_Player_delete00);
tolua_function(tolua_S,"setHealth",tolua_Player_Player_setHealth00);
tolua_function(tolua_S,"getHealth",tolua_Player_Player_getHealth00);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
TOLUA_API int tolua_Player_open(lua_State* tolua_S) {
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S, NULL, 0);
tolua_beginmodule(tolua_S, NULL);
#ifdef __cplusplus
tolua_cclass(
tolua_S, "Player", "Player", "", tolua_collect_Player);
#else
tolua_cclass(tolua_S, "Player", "Player", "", NULL);
#endif
tolua_beginmodule(tolua_S, "Player");
tolua_function(tolua_S, "new", tolua_Player_Player_new00);
tolua_function(
tolua_S, "new_local", tolua_Player_Player_new00_local);
tolua_function(
tolua_S, ".call", tolua_Player_Player_new00_local);
tolua_function(
tolua_S, "delete", tolua_Player_Player_delete00);
tolua_function(
tolua_S, "setHealth", tolua_Player_Player_setHealth00);
tolua_function(
tolua_S, "getHealth", tolua_Player_Player_getHealth00);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
TOLUA_API int luaopen_Player (lua_State* tolua_S) {
return tolua_Player_open(tolua_S);
TOLUA_API int luaopen_Player(lua_State* tolua_S) {
return tolua_Player_open(tolua_S);
};
#endif

View File

@ -1,4 +1,4 @@
# # # # sol3
# # # # sol2
# The MIT License (MIT)
#
# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors
@ -20,7 +20,7 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# # # sol3 Examples - require_from_dll
# # # sol2 Examples - require_from_dll
# # Reusable function to call for single target
# # Also hides variables from directory/global scope

View File

@ -16,7 +16,8 @@ namespace my_object {
#define MY_OBJECT_API __declspec(dllexport)
#else
#define MY_OBJECT_API __declspec(dllexport)
#endif // MY_OBJECT_BUILD - Building the Library vs. Using the Library
#endif // MY_OBJECT_BUILD - Building the Library vs. Using the
// Library
#else
#define MY_OBJECT_API
#endif // Building a DLL vs. Static Library

View File

@ -8,7 +8,10 @@ namespace my_object {
sol::table open_my_object(sol::this_state L) {
sol::state_view lua(L);
sol::table module = lua.create_table();
module.new_usertype<test>("test", sol::constructors<test(), test(int)>(), "value", &test::value);
module.new_usertype<test>("test",
sol::constructors<test(), test(int)>(),
"value",
&test::value);
return module;
}
@ -19,7 +22,9 @@ extern "C" int luaopen_my_object(lua_State* L) {
// pass the lua_State,
// the index to start grabbing arguments from,
// and the function itself
// optionally, you can pass extra arguments to the function if that's necessary,
// but that's advanced usage and is generally reserved for internals only
return sol::stack::call_lua(L, 1, my_object::open_my_object);
// optionally, you can pass extra arguments to the function
// if that's necessary, but that's advanced usage and is
// generally reserved for internals only
return sol::stack::call_lua(
L, 1, my_object::open_my_object);
}

View File

@ -16,13 +16,16 @@ mo = require("my_object")
obj = mo.test.new(24)
print(obj.value))";
auto script_result = lua.safe_script(code, &sol::script_pass_on_error);
auto script_result
= lua.safe_script(code, &sol::script_pass_on_error);
if (script_result.valid()) {
std::cout << "The DLL was require'd from successfully!" << std::endl;
std::cout << "The DLL was require'd from successfully!"
<< std::endl;
}
else {
sol::error err = script_result;
std::cout << "Something bad happened: " << err.what() << std::endl;
std::cout << "Something bad happened: " << err.what()
<< std::endl;
}
sol_c_assert(script_result.valid());
my_object::test& obj = lua["obj"];

View File

@ -8,12 +8,20 @@ class memory_tracker {
public:
// 10 MB or something?
// idk whatever
inline static constexpr std::size_t arbitrary_default_limit = 1024 * 1024 * 10;
inline static constexpr std::size_t arbitrary_default_limit
= 1024 * 1024 * 10;
memory_tracker() : memory_tracker(arbitrary_default_limit) {
}
memory_tracker(std::size_t maximum_memory) : used(0), limit(maximum_memory), n_threads(0), n_tables(0), n_functions(0), n_userdata(0), n_strings(0) {
memory_tracker(std::size_t maximum_memory)
: used(0)
, limit(maximum_memory)
, n_threads(0)
, n_tables(0)
, n_functions(0)
, n_userdata(0)
, n_strings(0) {
}
std::size_t currently_used() const {
@ -24,17 +32,22 @@ public:
return limit;
}
static void* allocate(void* memory_tracker_ud, void* ptr, size_t object_code, size_t nsize) {
memory_tracker& self = (*static_cast<memory_tracker*>(memory_tracker_ud));
static void* allocate(void* memory_tracker_ud, void* ptr,
size_t object_code, size_t nsize) {
memory_tracker& self = (*static_cast<memory_tracker*>(
memory_tracker_ud));
return self.alloc(ptr, object_code, nsize);
}
private:
void* alloc(void* ptr, size_t original_block_size_or_code, size_t new_block_size) {
std::size_t original_block_size = original_block_size_or_code;
void* alloc(void* ptr, size_t original_block_size_or_code,
size_t new_block_size) {
std::size_t original_block_size
= original_block_size_or_code;
if (ptr == nullptr) {
// object code!
sol::type object_type = static_cast<sol::type>(original_block_size_or_code);
sol::type object_type = static_cast<sol::type>(
original_block_size_or_code);
switch (object_type) {
case sol::type::function:
++n_functions;
@ -70,7 +83,8 @@ private:
}
// did we hit the limit?
std::size_t memory_differntial = new_block_size - original_block_size;
std::size_t memory_differntial
= new_block_size - original_block_size;
std::size_t desired_use = used + memory_differntial;
if (desired_use > limit) {
// tell the Lua Virtual Machine
@ -111,25 +125,45 @@ int main() {
std::cout << "=== memory tracker ===" << std::endl;
#if SOL_LUAJIT_VERSION < 20100 && (UINTPTR_MAX > 0xFFFFFFFF)
std::cout << "LuaJIT in x64 mode on LuaJIT 2.0.X versions does not support using a custom allocator!" << std::endl;
std::cout << "LuaJIT in x64 mode on LuaJIT 2.0.X versions "
"does not support using a custom allocator!"
<< std::endl;
#else
memory_tracker box;
std::cout << "memory at start: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
sol::state lua(&sol::default_at_panic, &memory_tracker::allocate, &box);
std::cout << "memory at start: " << box.currently_used()
<< " bytes / " << box.memory_limit() << " bytes"
<< std::endl;
sol::state lua(&sol::default_at_panic,
&memory_tracker::allocate,
&box);
lua.open_libraries(sol::lib::base);
std::cout << "memory after state creation: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
std::cout << "memory after state creation: "
<< box.currently_used() << " bytes / "
<< box.memory_limit() << " bytes" << std::endl;
// trigger some allocations
lua.new_usertype<my_type>("my_type", "a", &my_type::a, "b", &my_type::b, "d", &my_type::d);
lua.new_usertype<my_type>("my_type",
"a",
&my_type::a,
"b",
&my_type::b,
"d",
&my_type::d);
lua["f"] = [](std::string s) { return s + " woof!"; };
std::cout << "memory after function and usertype setup: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
std::cout << "memory after function and usertype setup: "
<< box.currently_used() << " bytes / "
<< box.memory_limit() << " bytes" << std::endl;
lua.safe_script("print(f('bark'))");
lua.safe_script("local obj = my_type.new() print(obj.a, obj.b, obj.c) obj.b = true print(obj.a, obj.b, obj.c)");
lua.safe_script(
"local obj = my_type.new() print(obj.a, obj.b, obj.c) "
"obj.b = true print(obj.a, obj.b, obj.c)");
std::cout << "memory at end: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
std::cout << "memory at end: " << box.currently_used()
<< " bytes / " << box.memory_limit() << " bytes"
<< std::endl;
#endif
return 0;
}

View File

@ -3,17 +3,21 @@
#include <iostream>
// Uses some of the fancier bits of sol3, including the "transparent argument",
// sol::this_state, which gets the current state and does not increment
// function arguments
sol::object fancy_func(sol::object a, sol::object b, sol::this_state s) {
// Uses some of the fancier bits of sol2, including the
// "transparent argument", sol::this_state, which gets the
// current state and does not increment function arguments
sol::object fancy_func(
sol::object a, sol::object b, sol::this_state s) {
sol::state_view lua(s);
if (a.is<int>() && b.is<int>()) {
return sol::object(lua, sol::in_place, a.as<int>() + b.as<int>());
return sol::object(
lua, sol::in_place, a.as<int>() + b.as<int>());
}
else if (a.is<bool>()) {
bool do_triple = a.as<bool>();
return sol::object(lua, sol::in_place_type<double>, b.as<double>() * (do_triple ? 3 : 1));
return sol::object(lua,
sol::in_place_type<double>,
b.as<double>() * (do_triple ? 3 : 1));
}
// Can also use make_object
return sol::make_object(lua, sol::lua_nil);
@ -32,7 +36,8 @@ int main() {
sol_c_assert(result2 == 2.5);
// call in Lua, get result
// notice we only need 2 arguments here, not 3 (sol::this_state is transparent)
// notice we only need 2 arguments here, not 3
// (sol::this_state is transparent)
lua.script("result3 = f(true, 5.5)");
double result3 = lua["result3"];
// result3 == 16.5

View File

@ -9,7 +9,9 @@ int main() {
sol::state lua;
lua.set_function("f", []() {
std::set<std::string> results { "arf", "bark", "woof" };
std::set<std::string> results {
"arf", "bark", "woof"
};
return sol::as_returns(std::move(results));
});

View File

@ -18,42 +18,58 @@ int main() {
// call lua code directly
lua.script("print('hello world')");
// call lua code, and check to make sure it has loaded and run properly:
// call lua code, and check to make sure it has loaded and
// run properly:
auto handler = &sol::script_default_on_error;
lua.script("print('hello again, world')", handler);
// Use a custom error handler if you need it
// This gets called when the result is bad
auto simple_handler = [](lua_State*, sol::protected_function_result result) {
// You can just pass it through to let the call-site handle it
return result;
};
// the above lambda is identical to sol::simple_on_error, but it's
// shown here to show you can write whatever you like
auto simple_handler =
[](lua_State*, sol::protected_function_result result) {
// You can just pass it through to let the
// call-site handle it
return result;
};
// the above lambda is identical to sol::simple_on_error,
// but it's shown here to show you can write whatever you
// like
//
{
auto result = lua.script("print('hello hello again, world') \n return 24", simple_handler);
auto result = lua.script(
"print('hello hello again, world') \n return 24",
simple_handler);
if (result.valid()) {
std::cout << "the third script worked, and a double-hello statement should appear above this one!" << std::endl;
std::cout << "the third script worked, and a "
"double-hello statement should "
"appear above this one!"
<< std::endl;
int value = result;
sol_c_assert(value == 24);
}
else {
std::cout << "the third script failed, check the result type for more information!" << std::endl;
std::cout << "the third script failed, check the "
"result type for more information!"
<< std::endl;
}
}
{
auto result = lua.script("does.not.exist", simple_handler);
auto result
= lua.script("does.not.exist", simple_handler);
if (result.valid()) {
std::cout << "the fourth script worked, which it wasn't supposed to! Panic!" << std::endl;
std::cout << "the fourth script worked, which it "
"wasn't supposed to! Panic!"
<< std::endl;
int value = result;
sol_c_assert(value == 24);
}
else {
sol::error err = result;
std::cout << "the fourth script failed, which was intentional!\t\nError: " << err.what() << std::endl;
std::cout << "the fourth script failed, which "
"was intentional!\t\nError: "
<< err.what() << std::endl;
}
}

View File

@ -13,12 +13,16 @@ struct something {
int main() {
std::cout << "=== c arrays (works with Visual C++ too) ===" << std::endl;
std::cout << "=== c arrays (works with Visual C++ too) ==="
<< std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<something>("something", "arr", sol::property([](something& s) { return std::ref(s.arr); }));
lua.new_usertype<something>(
"something", "arr", sol::property([](something& s) {
return std::ref(s.arr);
}));
lua.script(R"(s = something.new()
print(s.arr[3])
s.arr[3] = 40

View File

@ -19,7 +19,10 @@ int main() {
sol::state lua;
// overloaded function f
lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>);
lua.set("f",
sol::c_call<sol::wrap<decltype(&f1), &f1>,
sol::wrap<decltype(&f2), &f2>,
sol::wrap<decltype(&fer::f3), &fer::f3>>);
// singly-wrapped function
lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>);
// without the 'sol::wrap' boilerplate

View File

@ -11,10 +11,13 @@ std::string func_2(std::string text) {
return "received: " + text;
}
sol::variadic_results fallback(sol::this_state ts, sol::variadic_args args) {
sol::variadic_results fallback(
sol::this_state ts, sol::variadic_args args) {
sol::variadic_results r;
if (args.size() == 2) {
r.push_back({ ts, sol::in_place, args.get<int>(0) + args.get<int>(1) });
r.push_back({ ts,
sol::in_place,
args.get<int>(0) + args.get<int>(1) });
}
else {
r.push_back({ ts, sol::in_place, 52 });
@ -28,22 +31,28 @@ int main(int, char*[]) {
sol::state lua;
lua.open_libraries();
sol::table mLuaPackets = lua.create_named_table("mLuaPackets");
sol::table mLuaPackets
= lua.create_named_table("mLuaPackets");
mLuaPackets[1] = lua.create_table_with("timestamp", 0LL);
mLuaPackets[2] = lua.create_table_with("timestamp", 3LL);
mLuaPackets[3] = lua.create_table_with("timestamp", 1LL);
lua.script("print('--- pre sort ---')");
lua.script("for i=1,#mLuaPackets do print(i, mLuaPackets[i].timestamp) end");
lua.script(
"for i=1,#mLuaPackets do print(i, "
"mLuaPackets[i].timestamp) end");
lua["table"]["sort"](mLuaPackets, sol::as_function([](sol::table l, sol::table r) {
std::uint64_t tl = l["timestamp"];
std::uint64_t tr = r["timestamp"];
return tl < tr;
}));
lua["table"]["sort"](mLuaPackets,
sol::as_function([](sol::table l, sol::table r) {
std::uint64_t tl = l["timestamp"];
std::uint64_t tr = r["timestamp"];
return tl < tr;
}));
lua.script("print('--- post sort ---')");
lua.script("for i=1,#mLuaPackets do print(i, mLuaPackets[i].timestamp) end");
lua.script(
"for i=1,#mLuaPackets do print(i, "
"mLuaPackets[i].timestamp) end");
return 0;
}

View File

@ -12,15 +12,17 @@ struct config {
int height;
void print() {
std::cout << "Name: " << name << '\n' << "Width: " << width << '\n' << "Height: " << height << '\n';
std::cout << "Name: " << name << '\n'
<< "Width: " << width << '\n'
<< "Height: " << height << '\n';
}
};
int main() {
sol::state lua;
config screen;
// To use the file, uncomment here and make sure it is in local dir
// lua.script_file("config.lua");
// To use the file, uncomment here and make sure it is in
// local dir lua.script_file("config.lua");
lua.script(R"(
name = "Asus"
width = 1920

View File

@ -54,9 +54,15 @@ int main(int, char*[]) {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<number_storage>(
"number_storage", sol::constructors<number_storage(int)>(), "accumulate", &number_storage::accumulate, "iterable", [](number_storage& ns) {
return sol::as_container(ns); // treat like a container, despite is_container specialization
lua.new_usertype<number_storage>("number_storage",
sol::constructors<number_storage(int)>(),
"accumulate",
&number_storage::accumulate,
"iterable",
[](number_storage& ns) {
return sol::as_container(
ns); // treat like a container, despite
// is_container specialization
});
lua.script(R"(

View File

@ -7,7 +7,8 @@
int main() {
struct hasher {
typedef std::pair<std::string, std::string> argument_type;
typedef std::pair<std::string, std::string>
argument_type;
typedef std::size_t result_type;
result_type operator()(const argument_type& p) const {
@ -15,21 +16,30 @@ int main() {
}
};
using my_set = std::unordered_set<std::pair<std::string, std::string>, hasher>;
using my_set = std::unordered_set<
std::pair<std::string, std::string>,
hasher>;
std::cout << "=== containers with std::pair<> ===" << std::endl;
std::cout << "=== containers with std::pair<> ==="
<< std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.set_function("f", []() { return my_set { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" } }; });
lua.set_function("f", []() {
return my_set { { "key1", "value1" },
{ "key2", "value2" },
{ "key3", "value3" } };
});
lua.safe_script("v = f()");
lua.safe_script("print('v:', v)");
lua.safe_script("print('#v:', #v)");
// note that using my_obj:pairs() is a
// way around pairs(my_obj) not working in Lua 5.1/LuaJIT: try it!
lua.safe_script("for k,v1,v2 in v:pairs() do print(k, v1, v2) end");
// way around pairs(my_obj) not working in Lua 5.1/LuaJIT:
// try it!
lua.safe_script(
"for k,v1,v2 in v:pairs() do print(k, v1, v2) end");
std::cout << std::endl;

View File

@ -6,12 +6,14 @@
#include <iostream>
// nested allows serialization of maps with vectors inside, and vice-versa
// all from a nested structure of Lua tables
// it has less control over which pieces are considered tables in Lua,
// and which ones are considered userdata, but it covers a good 90% of cases
// where someone wants to handle a nested table
void demo(sol::nested<std::map<std::string, std::vector<std::string>>> src) {
// nested allows serialization of maps with vectors inside, and
// vice-versa all from a nested structure of Lua tables it has
// less control over which pieces are considered tables in Lua,
// and which ones are considered userdata, but it covers a good
// 90% of cases where someone wants to handle a nested table
void demo(
sol::nested<std::map<std::string, std::vector<std::string>>>
src) {
std::cout << "demo, sol::nested<...>" << std::endl;
const auto& listmap = src.value();
sol_c_assert(listmap.size() == 2);
@ -32,17 +34,24 @@ void demo(sol::nested<std::map<std::string, std::vector<std::string>>> src) {
// Nota bene the signature here
// Every container-type that's meant to be
// a table must be wrapped in `sol::as_table_t`
// it's verbose, so feel free to use typedefs to make it easy on you
// you can mix which parts are considered tables from Lua, and which parts
// are considered other kinds of types, such as userdata and the like
void demo_explicit(sol::as_table_t<std::map<std::string, sol::as_table_t<std::vector<std::string>>>> src) {
std::cout << "demo, explicit sol::as_table_t<...>" << std::endl;
// Have to access the "source" member variable for as_table_t
// it's verbose, so feel free to use typedefs to make it easy on
// you you can mix which parts are considered tables from Lua,
// and which parts are considered other kinds of types, such as
// userdata and the like
void demo_explicit(sol::as_table_t<std::map<std::string,
sol::as_table_t<std::vector<std::string>>>>
src) {
std::cout << "demo, explicit sol::as_table_t<...>"
<< std::endl;
// Have to access the "source" member variable for
// as_table_t
const auto& listmap = src.value();
sol_c_assert(listmap.size() == 2);
for (const auto& kvp : listmap) {
// Have to access the internal "source" for the inner as_table_t, as well
const std::vector<std::string>& strings = kvp.second.value();
// Have to access the internal "source" for the inner
// as_table_t, as well
const std::vector<std::string>& strings
= kvp.second.value();
sol_c_assert(strings.size() == 3);
std::cout << "\t" << kvp.first << " = ";
for (const auto& s : strings) {
@ -55,13 +64,15 @@ void demo_explicit(sol::as_table_t<std::map<std::string, sol::as_table_t<std::ve
}
int main(int, char**) {
std::cout << "=== containers retrieved from lua tables ===" << std::endl;
std::cout << "=== containers retrieved from lua tables ==="
<< std::endl;
sol::state lua;
// bind the function
lua.set_function("f", &demo);
lua.set_function("g", &demo_explicit);
// Call it with a table that has string sequences set to distinct keys
// Call it with a table that has string sequences set to
// distinct keys
lua.script(R"(
t = {
key1 = {'hello', 'there', 'world'},

View File

@ -14,26 +14,34 @@ int main() {
sol::thread runner_thread = sol::thread::create(lua);
lua.set_function("start_task", [&runner_thread, &tasks](sol::function f, sol::variadic_args va) {
// You must ALWAYS get the current state
sol::state_view runner_thread_state = runner_thread.state();
// Put the task in our task list to keep it alive and track it
std::size_t task_index = tasks.size();
tasks.emplace_back(runner_thread_state, f);
sol::coroutine& f_on_runner_thread = tasks[task_index];
// call coroutine with arguments that came
// from main thread / other thread
// pusher for `variadic_args` and other sol types will transfer the
// arguments from the calling thread to
// the runner thread automatically for you
// using `lua_xmove` internally
int wait = f_on_runner_thread(va);
std::cout << "First return: " << wait << std::endl;
// When you call it again, you don't need new arguments
// (they remain the same from the first call)
f_on_runner_thread();
std::cout << "Second run complete: " << wait << std::endl;
});
lua.set_function("start_task",
[&runner_thread, &tasks](
sol::function f, sol::variadic_args va) {
// You must ALWAYS get the current state
sol::state_view runner_thread_state
= runner_thread.state();
// Put the task in our task list to keep it alive
// and track it
std::size_t task_index = tasks.size();
tasks.emplace_back(runner_thread_state, f);
sol::coroutine& f_on_runner_thread
= tasks[task_index];
// call coroutine with arguments that came
// from main thread / other thread
// pusher for `variadic_args` and other sol types
// will transfer the arguments from the calling
// thread to the runner thread automatically for
// you using `lua_xmove` internally
int wait = f_on_runner_thread(va);
std::cout << "First return: " << wait
<< std::endl;
// When you call it again, you don't need new
// arguments (they remain the same from the first
// call)
f_on_runner_thread();
std::cout << "Second run complete: " << wait
<< std::endl;
});
lua.script(
R"(

View File

@ -5,13 +5,19 @@
#include <iostream>
int main() {
std::cout << "=== coroutine - multple threads ===" << std::endl;
std::cout << "=== coroutine - multple threads ==="
<< std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::coroutine);
lua.open_libraries(sol::lib::base,
sol::lib::package,
sol::lib::coroutine);
lua["print"] = [](sol::object v) { std::cout << v.as<std::string>() << std::endl; };
lua["cyield"] = sol::yielding([]() { std::cout << "YIELDING" << std::endl; });
lua["print"] = [](sol::object v) {
std::cout << v.as<std::string>() << std::endl;
};
lua["cyield"] = sol::yielding(
[]() { std::cout << "YIELDING" << std::endl; });
// notice the new threads!
sol::thread thread1 = sol::thread::create(lua);

View File

@ -4,17 +4,21 @@
#include <iostream>
int main(int, char*[]) {
std::cout << "=== coroutine state transfer ===" << std::endl;
std::cout << "=== coroutine state transfer ==="
<< std::endl;
sol::state lua;
lua.open_libraries();
sol::function transferred_into;
lua["f"] = [&lua, &transferred_into](sol::object t, sol::this_state this_L) {
std::cout << "state of main : " << (void*)lua.lua_state() << std::endl;
std::cout << "state of function : " << (void*)this_L.lua_state() << std::endl;
// pass original lua_State* (or sol::state/sol::state_view)
// transfers ownership from the state of "t",
// to the "lua" sol::state
lua["f"] = [&lua, &transferred_into](
sol::object t, sol::this_state this_L) {
std::cout << "state of main : "
<< (void*)lua.lua_state() << std::endl;
std::cout << "state of function : "
<< (void*)this_L.lua_state() << std::endl;
// pass original lua_State* (or
// sol::state/sol::state_view) transfers ownership from
// the state of "t", to the "lua" sol::state
transferred_into = sol::function(lua, t);
};

View File

@ -18,11 +18,13 @@ struct custom_reader {
std::size_t current_size;
std::size_t read_count;
custom_reader(FILE* f_) : f(f_), buffer(), current_size(0), read_count(0) {
custom_reader(FILE* f_)
: f(f_), buffer(), current_size(0), read_count(0) {
}
bool read() {
std::cout << "custom read: read #" << ++read_count << std::endl;
std::cout << "custom read: read #" << ++read_count
<< std::endl;
current_size = fread(buffer, 1, 2, f);
return current_size > 0 && ferror(f) == 0;
}
@ -34,8 +36,10 @@ struct custom_reader {
// function must match signature found in type lua_Reader:
// const char* ( lua_State*, void*, size_t* )
const char* custom_reader_function(lua_State*, void* pointer_to_my_object, size_t* data_size) {
custom_reader& cr = *(static_cast<custom_reader*>(pointer_to_my_object));
const char* custom_reader_function(
lua_State*, void* pointer_to_my_object, size_t* data_size) {
custom_reader& cr
= *(static_cast<custom_reader*>(pointer_to_my_object));
if (cr.read()) {
*data_size = cr.current_size;
return cr.buffer;
@ -68,20 +72,24 @@ int main() {
FILE* bjork_fp;
#ifdef _MSC_VER
if (fopen_s(&bjork_fp, "bjork.lua", "r") != 0) {
std::cerr << "failed to open bjork.lua -- exiting" << std::endl;
std::cerr << "failed to open bjork.lua -- exiting"
<< std::endl;
return -1;
}
#else
bjork_fp = fopen("bjork.lua", "r");
#endif
if (bjork_fp == nullptr) {
std::cerr << "failed to open bjork.lua -- exiting" << std::endl;
std::cerr << "failed to open bjork.lua -- exiting"
<< std::endl;
return -1;
}
custom_reader reader(bjork_fp);
// load the code using our custom reader, then run it
auto result = lua.safe_script(custom_reader_function, &reader, sol::script_pass_on_error);
auto result = lua.safe_script(custom_reader_function,
&reader,
sol::script_pass_on_error);
// make sure we ran loaded and ran the code successfully
sol_c_assert(result.valid());

View File

@ -31,10 +31,12 @@ public:
// helper function defined later after we define all the
// base classes we care about
sol::object getAsRetyped(lua_State* L, BaseObjectLifetime Lifetime) const;
sol::object getAsRetyped(
lua_State* L, BaseObjectLifetime Lifetime) const;
// For convenience with the customization points below
int pushAsRetyped(lua_State* L, BaseObjectLifetime Lifetime) const {
int pushAsRetyped(
lua_State* L, BaseObjectLifetime Lifetime) const {
return getAsRetyped(L, Lifetime).push(L);
}
@ -67,30 +69,41 @@ public:
// Get the most-derived type
// that we care about from the base object,
// obeying the lifetime type
sol::object BaseObject::getAsRetyped(lua_State* L, BaseObjectLifetime Lifetime) const {
sol::object BaseObject::getAsRetyped(
lua_State* L, BaseObjectLifetime Lifetime) const {
switch (objectType) {
case 1:
std::cout << "Retyping as armor." << std::endl;
switch (Lifetime) {
case BaseObjectLifetime::Value:
return sol::make_object(L, *static_cast<const Armor*>(this));
return sol::make_object(
L, *static_cast<const Armor*>(this));
case BaseObjectLifetime::Pointer:
return sol::make_object(L, static_cast<const Armor*>(this));
return sol::make_object(
L, static_cast<const Armor*>(this));
case BaseObjectLifetime::Shared:
return sol::make_object(L, std::make_shared<Armor>(*static_cast<const Armor*>(this)));
return sol::make_object(L,
std::make_shared<Armor>(
*static_cast<const Armor*>(this)));
}
case 2:
std::cout << "Retyping as weapon." << std::endl;
switch (Lifetime) {
case BaseObjectLifetime::Value:
return sol::make_object(L, *static_cast<const Weapon*>(this));
return sol::make_object(
L, *static_cast<const Weapon*>(this));
case BaseObjectLifetime::Pointer:
return sol::make_object(L, static_cast<const Weapon*>(this));
return sol::make_object(
L, static_cast<const Weapon*>(this));
case BaseObjectLifetime::Shared:
return sol::make_object(L, std::make_shared<Weapon>(*static_cast<const Weapon*>(this)));
return sol::make_object(L,
std::make_shared<Weapon>(
*static_cast<const Weapon*>(this)));
}
default:
std::cout << "Unknown type: falling back to base object." << std::endl;
std::cout
<< "Unknown type: falling back to base object."
<< std::endl;
// we have a normal type here, so that means we
// must bypass typical customization points by using
// sol::make_object_userdata/sol::make_reference_userdata
@ -104,7 +117,8 @@ sol::object BaseObject::getAsRetyped(lua_State* L, BaseObjectLifetime Lifetime)
case BaseObjectLifetime::Value:
return sol::make_object_userdata(L, *this);
case BaseObjectLifetime::Shared:
return sol::make_object_userdata(L, std::make_shared<BaseObject>(*this));
return sol::make_object_userdata(
L, std::make_shared<BaseObject>(*this));
case BaseObjectLifetime::Pointer:
default:
return sol::make_object_userdata(L, this);
@ -116,36 +130,47 @@ sol::object BaseObject::getAsRetyped(lua_State* L, BaseObjectLifetime Lifetime)
// sol customization points
//
// Defining a customization point that lets us put the correct object type on the stack.
int sol_lua_push(sol::types<BaseObject>, lua_State* L, const BaseObject& obj) {
// Defining a customization point that lets us put the correct
// object type on the stack.
int sol_lua_push(sol::types<BaseObject>, lua_State* L,
const BaseObject& obj) {
return obj.pushAsRetyped(L, BaseObjectLifetime::Value);
}
int sol_lua_push(sol::types<BaseObject*>, lua_State* L, const BaseObject* obj) {
int sol_lua_push(sol::types<BaseObject*>, lua_State* L,
const BaseObject* obj) {
return obj->pushAsRetyped(L, BaseObjectLifetime::Pointer);
}
int sol_lua_push(sol::types<std::shared_ptr<BaseObject>>, lua_State* L, const std::shared_ptr<BaseObject>& obj) {
int sol_lua_push(sol::types<std::shared_ptr<BaseObject>>,
lua_State* L, const std::shared_ptr<BaseObject>& obj) {
return obj->pushAsRetyped(L, BaseObjectLifetime::Shared);
}
int main() {
// test our customization points out
std::cout << "=== Base object customization points ===" << std::endl;
std::cout << "=== Base object customization points ==="
<< std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::table);
lua.open_libraries(
sol::lib::base, sol::lib::string, sol::lib::table);
lua["objectCache"] = lua.create_table();
// Do basic type binding.
auto luaBaseObject = lua.new_usertype<BaseObject>("tes3baseObject");
luaBaseObject["objectType"] = sol::readonly_property(&BaseObject::getObjectType);
auto luaBaseObject
= lua.new_usertype<BaseObject>("tes3baseObject");
luaBaseObject["objectType"]
= sol::readonly_property(&BaseObject::getObjectType);
luaBaseObject["doArmorThing"] = &BaseObject::doArmorThing;
luaBaseObject["doWeaponThing"] = &BaseObject::doWeaponThing;
auto luaArmorObject = lua.new_usertype<Armor>("tes3armor");
luaArmorObject[sol::base_classes] = sol::bases<BaseObject>();
luaArmorObject[sol::base_classes]
= sol::bases<BaseObject>();
luaArmorObject["doArmorThing"] = &Armor::doArmorThing;
auto luaWeaponObject = lua.new_usertype<Weapon>("tes3weapon");
luaWeaponObject[sol::base_classes] = sol::bases<BaseObject>();
auto luaWeaponObject
= lua.new_usertype<Weapon>("tes3weapon");
luaWeaponObject[sol::base_classes]
= sol::bases<BaseObject>();
luaWeaponObject["doWeaponThing"] = &Weapon::doWeaponThing;
// Objects we'll play with.
@ -173,10 +198,14 @@ int main() {
lua["sharedArmor"] = std::make_shared<Weapon>();
std::cout << std::endl;
std::cout << "Smart pointers put as the base class..." << std::endl;
lua["sharedBaseAsBase"] = (std::shared_ptr<BaseObject>)std::make_shared<BaseObject>();
lua["sharedArmorAsBase"] = (std::shared_ptr<BaseObject>)std::make_shared<Armor>();
lua["sharedArmorAsBase"] = (std::shared_ptr<BaseObject>)std::make_shared<Weapon>();
std::cout << "Smart pointers put as the base class..."
<< std::endl;
lua["sharedBaseAsBase"] = (std::shared_ptr<BaseObject>)
std::make_shared<BaseObject>();
lua["sharedArmorAsBase"] = (std::shared_ptr<BaseObject>)
std::make_shared<Armor>();
lua["sharedArmorAsBase"] = (std::shared_ptr<BaseObject>)
std::make_shared<Weapon>();
std::cout << std::endl;
return 0;

View File

@ -9,19 +9,30 @@ struct number_shim {
};
template <typename Handler>
bool sol_lua_check(sol::types<number_shim>, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) {
// check_usertype is a backdoor for directly checking sol3 usertypes
if (!sol::stack::check_usertype<number_shim>(L, index) && !sol::stack::check<double>(L, index)) {
handler(L, index, sol::type_of(L, index), sol::type::userdata, "expected a number_shim or a number");
bool sol_lua_check(sol::types<number_shim>, lua_State* L,
int index, Handler&& handler,
sol::stack::record& tracking) {
// check_usertype is a backdoor for directly checking sol2
// usertypes
if (!sol::stack::check_usertype<number_shim>(L, index)
&& !sol::stack::check<double>(L, index)) {
handler(L,
index,
sol::type_of(L, index),
sol::type::userdata,
"expected a number_shim or a number");
return false;
}
tracking.use(1);
return true;
}
number_shim sol_lua_get(sol::types<number_shim>, lua_State* L, int index, sol::stack::record& tracking) {
number_shim sol_lua_get(sol::types<number_shim>, lua_State* L,
int index, sol::stack::record& tracking) {
if (sol::stack::check_usertype<number_shim>(L, index)) {
number_shim& ns = sol::stack::get_usertype<number_shim>(L, index, tracking);
number_shim& ns
= sol::stack::get_usertype<number_shim>(
L, index, tracking);
return ns;
}
number_shim ns {};

View File

@ -2,14 +2,17 @@
#include <sol/sol.hpp>
// Something that can't be collided with
static const auto& script_key = "GlobalResource.MySpecialIdentifier123";
static const auto& script_key
= "GlobalResource.MySpecialIdentifier123";
struct GlobalResource {
int value = 2;
};
template <typename Handler>
bool sol_lua_check(sol::types<GlobalResource*>, lua_State* L, int /*index*/, Handler&& handler, sol::stack::record& tracking) {
bool sol_lua_check(sol::types<GlobalResource*>, lua_State* L,
int /*index*/, Handler&& handler,
sol::stack::record& tracking) {
// not actually taking anything off the stack
tracking.use(0);
// get the field from global storage
@ -18,26 +21,34 @@ bool sol_lua_check(sol::types<GlobalResource*>, lua_State* L, int /*index*/, Han
sol::type t = static_cast<sol::type>(lua_type(L, -1));
lua_pop(L, 1);
if (t != sol::type::lightuserdata) {
handler(L, 0, sol::type::lightuserdata, t, "global resource is not present as a light userdata");
handler(L,
0,
sol::type::lightuserdata,
t,
"global resource is not present as a light "
"userdata");
return false;
}
return true;
}
GlobalResource* sol_lua_get(sol::types<GlobalResource*>, lua_State* L, int /*index*/, sol::stack::record& tracking) {
GlobalResource* sol_lua_get(sol::types<GlobalResource*>,
lua_State* L, int /*index*/, sol::stack::record& tracking) {
// retrieve the (light) userdata for this type
// not actually pulling anything off the stack
tracking.use(0);
sol::stack::get_field<true>(L, script_key);
GlobalResource* ls = static_cast<GlobalResource*>(lua_touserdata(L, -1));
GlobalResource* ls
= static_cast<GlobalResource*>(lua_touserdata(L, -1));
// clean up stack value returned by `get_field`
lua_pop(L, 1);
return ls;
}
int sol_lua_push(sol::types<GlobalResource*>, lua_State* L, GlobalResource* ls) {
int sol_lua_push(sol::types<GlobalResource*>, lua_State* L,
GlobalResource* ls) {
// push light userdata
return sol::stack::push(L, static_cast<void*>(ls));
}
@ -50,7 +61,9 @@ int main() {
GlobalResource instance;
// get GlobalResource
lua.set_function("f", [](GlobalResource* l, int value) { return l->value + value; });
lua.set_function("f", [](GlobalResource* l, int value) {
return l->value + value;
});
lua.set(script_key, &instance);
// note only 1 argument,

View File

@ -9,19 +9,26 @@ struct two_things {
};
template <typename Handler>
bool sol_lua_check(sol::types<two_things>, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) {
// indices can be negative to count backwards from the top of the stack,
// rather than the bottom up
// to deal with this, we adjust the index to
// its absolute position using the lua_absindex function
bool sol_lua_check(sol::types<two_things>, lua_State* L,
int index, Handler&& handler,
sol::stack::record& tracking) {
// indices can be negative to count backwards from the top
// of the stack, rather than the bottom up to deal with
// this, we adjust the index to its absolute position using
// the lua_absindex function
int absolute_index = lua_absindex(L, index);
// Check first and second second index for being the proper types
bool success = sol::stack::check<int>(L, absolute_index, handler) && sol::stack::check<bool>(L, absolute_index + 1, handler);
// Check first and second second index for being the proper
// types
bool success
= sol::stack::check<int>(L, absolute_index, handler)
&& sol::stack::check<bool>(
L, absolute_index + 1, handler);
tracking.use(2);
return success;
}
two_things sol_lua_get(sol::types<two_things>, lua_State* L, int index, sol::stack::record& tracking) {
two_things sol_lua_get(sol::types<two_things>, lua_State* L,
int index, sol::stack::record& tracking) {
int absolute_index = lua_absindex(L, index);
// Get the first element
int a = sol::stack::get<int>(L, absolute_index);
@ -50,7 +57,8 @@ int main() {
lua.open_libraries(sol::lib::base);
// Create a pass-through style of function
lua.script("function f ( a, b ) print(a, b) return a, b end");
lua.script(
"function f ( a, b ) print(a, b) return a, b end");
// get the function out of Lua
sol::function f = lua["f"];

View File

@ -7,8 +7,11 @@ int main(int, char*[]) {
sol::state lua;
lua.open_libraries();
lua.set("my_table", sol::as_table(std::vector<int> { 1, 2, 3, 4, 5 }));
lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end");
lua.set("my_table",
sol::as_table(std::vector<int> { 1, 2, 3, 4, 5 }));
lua.script(
"for k, v in ipairs(my_table) do print(k, v) assert(k "
"== v) end");
return 0;
}

View File

@ -35,14 +35,15 @@ end
// we start from 0;
// we want 10 values, and we only want to
// run if the coroutine "loop_coroutine" is valid
for (int counter = 0; counter < 10 && loop_coroutine; ++counter) {
for (int counter = 0; counter < 10 && loop_coroutine;
++counter) {
// Alternative: counter < 10 && cr.valid()
// Call the coroutine, does the computation and then suspends
// once it returns, we get the value back from the return
// and then can use it
// we can either leave the coroutine like that can come to it later,
// or loop back around
// Call the coroutine, does the computation and then
// suspends once it returns, we get the value back from
// the return and then can use it we can either leave
// the coroutine like that can come to it later, or
// loop back around
int value = loop_coroutine();
std::cout << "In C++: " << value << std::endl;
}

View File

@ -27,8 +27,10 @@ end
sol::coroutine loop_coroutine = runnerstate["loop"];
lua["counter"] = 20;
for (int counter = 0; counter < 10 && loop_coroutine; ++counter) {
// Call the coroutine, does the computation and then suspends
for (int counter = 0; counter < 10 && loop_coroutine;
++counter) {
// Call the coroutine, does the computation and then
// suspends
int value = loop_coroutine();
std::cout << "value is " << value << std::endl;
}

View File

@ -22,7 +22,11 @@ int main(int, char*[]) {
lua.new_usertype<B>("A", "call", &A::call);
lua.new_usertype<B>("B", "call", &B::call, sol::base_classes, sol::bases<A>());
lua.new_usertype<B>("B",
"call",
&B::call,
sol::base_classes,
sol::bases<A>());
return 0;
}

View File

@ -3,21 +3,24 @@
#include <iostream>
inline void my_panic(sol::optional<std::string> maybe_msg) {
std::cerr << "Lua is in a panic state and will now abort() the application" << std::endl;
std::cerr << "Lua is in a panic state and will now abort() "
"the application"
<< std::endl;
if (maybe_msg) {
const std::string& msg = maybe_msg.value();
std::cerr << "\terror message: " << msg << std::endl;
}
// When this function exits, Lua will exhibit default behavior and abort()
// When this function exits, Lua will exhibit default
// behavior and abort()
}
int main(int, char*[]) {
sol::state lua(sol::c_call<decltype(&my_panic), &my_panic>);
// or, if you already have a lua_State* L
// lua_atpanic( L, sol::c_call<decltype(&my_panic), &my_panic> );
// or, with state/state_view:
// sol::state_view lua(L);
// lua.set_panic( sol::c_call<decltype(&my_panic), &my_panic> );
// lua_atpanic( L, sol::c_call<decltype(&my_panic),
// &my_panic> ); or, with state/state_view: sol::state_view
// lua(L); lua.set_panic( sol::c_call<decltype(&my_panic),
// &my_panic> );
// uncomment the below to see
// lua.script("boom_goes.the_dynamite");

View File

@ -13,7 +13,8 @@ int main(int, char*[]) {
my_env["var"] = 50;
my_env["print"] = lua["print"];
sol::environment my_other_env(lua, sol::create, lua.globals());
sol::environment my_other_env(
lua, sol::create, lua.globals());
// do not need to explicitly allow access to "print",
// since we used the "Set a fallback" version
// of the sol::environment constructor

View File

@ -19,7 +19,8 @@ int main(int, char*[]) {
// runtime additions: through the sol API
lua["object"]["func"] = [](object& o) { return o.value; };
// runtime additions: through a lua script
lua.script("function object:print () print(self:func()) end");
lua.script(
"function object:print () print(self:func()) end");
// see it work
lua.script("local obj = object.new() \n obj:print()");

View File

@ -12,7 +12,8 @@ struct vars {
int main() {
sol::state lua;
lua.new_usertype<vars>("vars", "boop", &vars::boop, "bop", &vars::bop);
lua.new_usertype<vars>(
"vars", "boop", &vars::boop, "bop", &vars::bop);
lua.script(
"beep = vars.new()\n"
"beep.boop = 1\n"

View File

@ -8,26 +8,35 @@ int main() {
std::cout << "=== safe_script usage ===" << std::endl;
sol::state lua;
// uses sol::script_default_on_error, which either panics or throws,
// depending on your configuration and compiler settings
// uses sol::script_default_on_error, which either panics or
// throws, depending on your configuration and compiler
// settings
try {
auto result1 = lua.safe_script("bad.code");
}
catch (const sol::error& e) {
std::cout << "an expected error has occurred: " << e.what() << std::endl;
std::cout << "an expected error has occurred: "
<< e.what() << std::endl;
}
// a custom handler that you write yourself
// is only called when an error happens with loading or running the script
auto result2 = lua.safe_script("123 bad.code", [](lua_State*, sol::protected_function_result pfr) {
// pfr will contain things that went wrong, for either loading or executing the script
// the user can do whatever they like here, including throw. Otherwise...
sol::error err = pfr;
std::cout << "An error (an expected one) occurred: " << err.what() << std::endl;
// is only called when an error happens with loading or
// running the script
auto result2 = lua.safe_script("123 bad.code",
[](lua_State*, sol::protected_function_result pfr) {
// pfr will contain things that went wrong, for
// either loading or executing the script the user
// can do whatever they like here, including
// throw. Otherwise...
sol::error err = pfr;
std::cout
<< "An error (an expected one) occurred: "
<< err.what() << std::endl;
// ... they need to return the protected_function_result
return pfr;
});
// ... they need to return the
// protected_function_result
return pfr;
});
std::cout << std::endl;

View File

@ -9,12 +9,15 @@ int main(int, char*[]) {
sol::state lua;
lua.open_libraries();
sol::function transferred_into;
lua["f"] = [&lua, &transferred_into](sol::object t, sol::this_state this_L) {
std::cout << "state of main : " << (void*)lua.lua_state() << std::endl;
std::cout << "state of function : " << (void*)this_L.lua_state() << std::endl;
// pass original lua_State* (or sol::state/sol::state_view)
// transfers ownership from the state of "t",
// to the "lua" sol::state
lua["f"] = [&lua, &transferred_into](
sol::object t, sol::this_state this_L) {
std::cout << "state of main : "
<< (void*)lua.lua_state() << std::endl;
std::cout << "state of function : "
<< (void*)this_L.lua_state() << std::endl;
// pass original lua_State* (or
// sol::state/sol::state_view) transfers ownership from
// the state of "t", to the "lua" sol::state
transferred_into = sol::function(lua, t);
};

View File

@ -25,8 +25,10 @@ struct worker_data {
void worker_thread(worker_data& data) {
for (std::uint64_t loops = 0; true; ++loops) {
// Wait until main() sends data
std::unique_lock<std::mutex> data_lock(data.until_ready_mutex);
data.until_ready_condition.wait(data_lock, [&data] { return data.is_ready; });
std::unique_lock<std::mutex> data_lock(
data.until_ready_mutex);
data.until_ready_condition.wait(
data_lock, [&data] { return data.is_ready; });
if (data.payload.size() == 0) {
// signaling we are done
@ -37,7 +39,8 @@ void worker_thread(worker_data& data) {
sol::state& lua = data.worker_lua;
// we own the lock now, do the work
std::variant<double, std::vector<double>> result = lua.safe_script(data.payload.as_string_view());
std::variant<double, std::vector<double>> result
= lua.safe_script(data.payload.as_string_view());
// store returning payload,
// clear current payload
@ -45,7 +48,8 @@ void worker_thread(worker_data& data) {
data.payload.clear();
// Send result back to main
std::cout << "worker_thread data processing is completed: signaling & unlocking\n";
std::cout << "worker_thread data processing is "
"completed: signaling & unlocking\n";
data.is_processed = true;
data.is_ready = false;
data_lock.unlock();
@ -88,9 +92,12 @@ int main() {
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(data.until_ready_mutex);
std::lock_guard<std::mutex> lk(
data.until_ready_mutex);
data.is_ready = true;
std::cout << "function serialized: sending to worker thread to execute on Lua state...\n";
std::cout
<< "function serialized: sending to worker "
"thread to execute on Lua state...\n";
}
data.until_ready_condition.notify_one();
@ -99,27 +106,43 @@ int main() {
}
// wait for the worker
{
std::unique_lock<std::mutex> lock_waiting_for_worker(data.until_ready_mutex);
data.until_ready_condition.wait(lock_waiting_for_worker, [&data] { return data.is_processed; });
std::unique_lock<std::mutex>
lock_waiting_for_worker(
data.until_ready_mutex);
data.until_ready_condition.wait(
lock_waiting_for_worker,
[&data] { return data.is_processed; });
data.is_processed = false;
}
auto data_processor = [](auto& returned_data) {
using option_type = std::remove_cv_t<std::remove_reference_t<decltype(returned_data)>>;
if constexpr (std::is_same_v<option_type, double>) {
std::cout << "received a double: " << returned_data << "\n";
using option_type
= std::remove_cv_t<std::remove_reference_t<
decltype(returned_data)>>;
if constexpr (std::is_same_v<option_type,
double>) {
std::cout << "received a double: "
<< returned_data << "\n";
}
else if constexpr (std::is_same_v<option_type, std::vector<double>>) {
std::cout << "received a std::vector<double>: { ";
for (std::size_t i = 0; i < returned_data.size(); ++i) {
else if constexpr (std::is_same_v<option_type,
std::vector<double>>) {
std::cout
<< "received a std::vector<double>: { ";
for (std::size_t i = 0;
i < returned_data.size();
++i) {
std::cout << returned_data[i];
if (i != static_cast<std::size_t>(returned_data.size() - 1)) {
if (i
!= static_cast<std::size_t>(
returned_data.size() - 1)) {
std::cout << ", ";
}
}
std::cout << " }\n";
}
else {
std::cerr << "OH MY GOD YOU FORGOT TO HANDLE A TYPE OF DATA FROM A WORKER ABORT ABORT ABORT\n";
std::cerr << "OH MY GOD YOU FORGOT TO "
"HANDLE A TYPE OF DATA FROM A "
"WORKER ABORT ABORT ABORT\n";
std::abort();
}
};

View File

@ -5,7 +5,8 @@
int main() {
std::cout << "=== dump (serialize between states) ===" << std::endl;
std::cout << "=== dump (serialize between states) ==="
<< std::endl;
// 2 states, transferring function from 1 to another
sol::state lua;
@ -18,17 +19,20 @@ int main() {
lua2.open_libraries(sol::lib::base);
// load this code (but do not run)
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
sol::load_result lr
= lua.load("a = function (v) print(v) return v end");
// check if it's sucessfully loaded
sol_c_assert(lr.valid());
// turn it into a function, then dump the bytecode
sol::protected_function target = lr.get<sol::protected_function>();
sol::protected_function target
= lr.get<sol::protected_function>();
sol::bytecode target_bc = target.dump();
// reload the byte code
// in the SECOND state
auto result2 = lua2.safe_script(target_bc.as_string_view(), sol::script_pass_on_error);
auto result2 = lua2.safe_script(
target_bc.as_string_view(), sol::script_pass_on_error);
// check if it was done properly
sol_c_assert(result2.valid());

Some files were not shown because too many files have changed in this diff Show More