mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
documentation fixes from feedback and fixes!
This commit is contained in:
parent
d3ccfa7426
commit
62f082d999
|
@ -49,4 +49,10 @@ The call ``woof(20)`` generates a :ref:`function_result<function-result>`, which
|
|||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) operator()( types<Ret...>, Args&&... args );
|
||||
|
||||
Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. Function assumes there are no runtime errors, and thusly will call the ``atpanic`` function if an error does occur.
|
||||
Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. Function assumes there are no runtime errors, and thusly will call the ``atpanic`` function if an error does occur.
|
||||
|
||||
|
||||
safety
|
||||
------
|
||||
|
||||
You can have functions here and on usertypes check to definitely make sure that the types passed to C++ functions are what they're supposed to be by adding a ``#define SOL_CHECK_ARGUMENTS`` before including Sol, or passing it on the command line. Otherwise, for speed reasons, these checks are only used where absolutely necessary (like discriminating between :doc:`overloads<overload>`)
|
|
@ -20,7 +20,7 @@ members
|
|||
template<typename T>
|
||||
decltype(auto) as() const;
|
||||
|
||||
Performs a cast of the item this reference refers to into the type ``T`` and returns it. It obeys the same rules as :doc:`sol::stack::get\<T><stack>`.
|
||||
Performs a cast of the item this reference refers to into the type ``T`` and returns it. It obeys the same rules as :ref:`sol::stack::get\<T><getter>`.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: type check
|
||||
|
|
|
@ -62,10 +62,10 @@ Thusly, doing the following in Lua:
|
|||
:linenos:
|
||||
|
||||
local barker = pup.new()
|
||||
pup.bark() -- calls member function pup::bark
|
||||
pup.bark(20) -- calls ultra_bark
|
||||
pup.bark("meow") -- picky_bark, no bark
|
||||
pup.bark("bark") -- picky_bark, bark
|
||||
pup:bark() -- calls member function pup::bark
|
||||
pup:bark(20) -- calls ultra_bark
|
||||
pup:bark("meow") -- picky_bark, no bark
|
||||
pup:bark("bark") -- picky_bark, bark
|
||||
|
||||
bark(pup, 20) -- calls ultra_bark
|
||||
local nowherebark = bark() -- calls lambda which returns that string
|
||||
|
|
|
@ -25,6 +25,7 @@ Retrieves the value of the object at ``index`` in the stack. The return type var
|
|||
|
||||
.. code-block:: cpp
|
||||
:caption: function: check
|
||||
:name: stack-check
|
||||
|
||||
template <typename T>
|
||||
bool check( lua_State* L, int index = -1 )
|
||||
|
@ -32,10 +33,11 @@ Retrieves the value of the object at ``index`` in the stack. The return type var
|
|||
template <typename T, typename Handler>
|
||||
bool check( lua_State* L, int index, Handler&& handler )
|
||||
|
||||
Checks if the object at ``index`` is of type ``T``. If it is not, it will call the ``handler`` function with the index, expected, and actual types.
|
||||
Checks if the object at ``index`` is of type ``T``. If it is not, it will call the ``handler`` function with ``lua_State*``, ``int index``, ``type`` expected, and ``type`` actual as arguments.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: push
|
||||
:name: stack-push
|
||||
|
||||
// push T inferred from call site, pass args... through to extension point
|
||||
template <typename T, typename... Args>
|
||||
|
@ -91,7 +93,7 @@ The structs below are already overriden for a handful of types. If you try to me
|
|||
}
|
||||
};
|
||||
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``get`` that returns a ``T``, or something convertible to it. The default implementation assumes ``T`` is a usertype and pulls out a userdata from Lua before attempting to cast it to the desired ``T``. There are implementations for getting numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata_value<types>` and anything as upvalues with :doc:`upvalue_index<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``std::function<R(Args...)>``. It is also defined for anything that derives from :doc:`sol::reference<reference>`.
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``get`` that returns a ``T``, or something convertible to it. The default implementation assumes ``T`` is a usertype and pulls out a userdata from Lua before attempting to cast it to the desired ``T``. There are implementations for getting numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata_value<types>` and anything as upvalues with :doc:`upvalue_index<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``std::function<R(Args...)>``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`).
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: struct: pusher
|
||||
|
@ -99,7 +101,7 @@ This is an SFINAE-friendly struct that is meant to expose static function ``get`
|
|||
|
||||
template <typename X, typename = void>
|
||||
struct pusher {
|
||||
template <typename T>
|
||||
template <typename T>
|
||||
static int push ( lua_State* L, T&&, ... ) {
|
||||
// can optionally take more than just 1 argument
|
||||
// ...
|
||||
|
@ -107,7 +109,7 @@ This is an SFINAE-friendly struct that is meant to expose static function ``get`
|
|||
}
|
||||
};
|
||||
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :ref:`usertype_traits\<T><usertype-traits>` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`.
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :ref:`usertype_traits\<T><usertype-traits>` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`).
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: struct: checker
|
||||
|
|
|
@ -45,6 +45,7 @@ These functions set items into the table. The first one (``set``) can set *mult
|
|||
|
||||
.. code-block:: cpp
|
||||
:caption: function: setting a usertype
|
||||
:name: new-usertype
|
||||
|
||||
template<typename Class, typename... Args>
|
||||
table& new_usertype(const std::string& name, Args&&... args);
|
||||
|
@ -59,6 +60,7 @@ This class of functions creates a new :doc:`usertype<usertype>` with the specifi
|
|||
|
||||
.. code-block:: cpp
|
||||
:caption: function: setting a pre-created usertype
|
||||
:name: set-usertype
|
||||
|
||||
template<typename T>
|
||||
table& set_usertype(usertype<T>& user);
|
||||
|
|
|
@ -27,3 +27,4 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
|
|||
types
|
||||
usertype
|
||||
userdata
|
||||
usertype_memory
|
||||
|
|
|
@ -123,6 +123,16 @@ special types
|
|||
A tag type that, when used with :doc:`stack::get\<non_null\<T*>><stack>`, does not perform a ``nil`` check when attempting to retrieve the userdata pointer.
|
||||
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: unique_usertype
|
||||
:name: unique-usertype
|
||||
|
||||
template <typename T, typename Real>
|
||||
struct unique_usertype {};
|
||||
|
||||
A tag type for alerting the framewok that a certain type is to be pushed as a special userdata with special deletion semantics. Is automatically applied to ``std::unique_ptr<T, D>`` and ``std::shared_ptr<T>``.
|
||||
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: type list
|
||||
:name: type-list
|
||||
|
|
|
@ -231,7 +231,6 @@ traits
|
|||
|
||||
.. code-block:: cpp
|
||||
:caption: usertype_traits<T>
|
||||
:linenos:
|
||||
:name: usertype-traits
|
||||
|
||||
template<typename T>
|
||||
|
@ -245,10 +244,9 @@ traits
|
|||
|
||||
This trait is used to provide names for the various metatables and global tables used to perform cleanup and lookup. They are automatically generated at runtime. In the case of RTTI being present, Sol will attempt to demangle the name from ``std::type_info`` to produce a valid name. If RTTI is disabled, Sol attempts to parse the output of ``__PRETTY_FUCNTION__`` (``g++``/``clang++``) or ``_FUNCDSIG`` (``vc++``) to get the proper type name. If you have a special need you can override the names for your specific type.
|
||||
|
||||
|
||||
performance note
|
||||
----------------
|
||||
|
||||
.. note::
|
||||
|
||||
Note that performance for member function calls goes down by a fixed overhead if you also bind variables as well as member functions. This is purely a limitation of the lua implementation and there's, unfortunately, nothing that can be done about it. If you bind only functions and no variables, however, Sol will automatically optimize the lua runtime and give you the maximum performance possible. *Please consider ease of use and maintenance of code before you make everything into functions.*
|
||||
Note that performance for member function calls goes down by a fixed overhead if you also bind variables as well as member functions. This is purely a limitation of the lua implementation and there's, unfortunately, nothing that can be done about it. If you bind only functions and no variables, however, Sol will automatically optimize the Lua runtime and give you the maximum performance possible. *Please consider ease of use and maintenance of code before you make everything into functions.*
|
||||
|
|
43
docs/source/api/usertype_memory.rst
Normal file
43
docs/source/api/usertype_memory.rst
Normal file
|
@ -0,0 +1,43 @@
|
|||
usertype memory
|
||||
===============
|
||||
|
||||
The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\<T><usertype-traits>`
|
||||
|
||||
In general, we always insert a T* in the first `sizeof(T*)` bytes, so the any framework that pulls out those first bytes expecting a pointer will work. The rest of the data has some different alignments and contents based on what it's used for and how it's used.
|
||||
|
||||
For ``T``
|
||||
---------
|
||||
|
||||
These are classified with the metatable from ``
|
||||
|
||||
The data layout for references is as follows::
|
||||
|
||||
| T* | T |
|
||||
^-sizeof(T*) bytes-^-sizeof(T) bytes, actual data-^
|
||||
|
||||
Lua will clean up the memory itself but does not know about any destruction semantics T may have imposed, so when we destroy this data we simply call the destructor to destroy the object and leave the memory changes to for lua to handle after the "__gc" method exits.
|
||||
|
||||
|
||||
For ``T*``
|
||||
----------
|
||||
|
||||
These are classified as a separate ``T*`` metatable, essentially the "reference" table. Things passed to Sol as a pointer or as a ``std::reference<T>`` are considered to be references, and thusly do not have a ``__gc`` (garbage collection) method by default. All raw pointers are non-owning pointers in C++. If you're working with a C API, provide a wrapper around pointers that are supposed to own data and use the constructor/destructor idioms (e.g., with an internal ``std::unique_ptr``) to keep things clean.
|
||||
|
||||
The data layout for data that only refers is as follows::
|
||||
|
||||
| T* |
|
||||
^-sizeof(T*) bytes-^
|
||||
|
||||
That is it. No destruction semantics need to be called.
|
||||
|
||||
For ``std::unique_ptr<T, D>`` and ``std::shared_ptr<T>``
|
||||
--------------------------------------------------------
|
||||
|
||||
These are classified as :ref:`"unique usertypes"<unique-usertype>`, and have a special metatable for them as well. The special metatable is either generated when you add the usertype to Lua using :ref:`set_usertype<set-usertype>` or when you first push one of these special types. In addition to the data, a deleter function that understands the following layout is injected into the usertype.
|
||||
|
||||
The data layout for these kinds of types is as follows::
|
||||
|
||||
| T* | void(*)(void*) function_pointer | T |
|
||||
^-sizeof(T*) bytes-^-sizeof(void(*)(void*)) bytes, deleter-^- sizeof(T) bytes, actal data -^
|
||||
|
||||
Note that we put a special deleter function before the actual data. This is because the custom deleter must know where the offset to the data is, not the rest of the library. Sol just needs to know about ``T*`` and the userdata (and userdata metatable) to work, everything else is for preserving construction / destruction syntax.
|
|
@ -87,13 +87,13 @@ The below feature table checks for the presence of something. It, however, does
|
|||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| thread | ✔ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ |
|
||||
| thread | ✔ | ✗ | ✗ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| coroutines | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| no-rtti support | ✔ | ✗ | ~ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ |
|
||||
| no-rtti support | ✔ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| no-exception support | ✔ | ✗ | ~ | ~ | ✗ | ✔ | ✗ | ✗ | ✔ |
|
||||
| no-exception support | ✔ | ✗ | ~ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
| Lua 5.1 | ✔ | ✔ | ~ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ |
|
||||
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
|
||||
|
@ -140,7 +140,7 @@ luabind -
|
|||
Selene -
|
||||
|
||||
* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get
|
||||
* Registering classes/"modules" in using C++ code is extremely verbose
|
||||
* Registering classes/"modules" using C++ code is extremely verbose
|
||||
|
||||
Sol -
|
||||
|
||||
|
@ -151,6 +151,7 @@ Sol -
|
|||
oolua -
|
||||
|
||||
* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs.`_
|
||||
* Supports not having exceptions or rtti turned on (shiny!)
|
||||
|
||||
.. _ fn1:
|
||||
|
||||
|
@ -167,5 +168,10 @@ kaguya -
|
|||
* Library author (satoren) is a nice guy!
|
||||
* C++11/14, or boostified (which makes it C++03 compatible)
|
||||
|
||||
TODO:
|
||||
* SWIG - http://www.swig.org/Doc1.3/Lua.html#Lua_nn2
|
||||
* SLB3 - https://code.google.com/archive/p/slb/
|
||||
* Luwra - https://github.com/vapourismo/luwra
|
||||
|
||||
|
||||
.. _Go read the docs.: https://oolua.org/docs/index.html
|
|
@ -83,7 +83,7 @@ the basics:
|
|||
"bop", &vars::bop);
|
||||
lua.script("beep = vars.new()\n"
|
||||
"beep.boop = 1\n"
|
||||
"bopvalue = beep.bop()");
|
||||
"bopvalue = beep:bop()");
|
||||
|
||||
vars& beep = lua["beep"];
|
||||
int bopvalue = lua["bopvalue"];
|
||||
|
|
|
@ -58,9 +58,9 @@ inline std::string get_type_name() {
|
|||
std::string name = __FUNCSIG__;
|
||||
std::size_t start = name.find("get_type_name");
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
start = 0;
|
||||
else
|
||||
start += 13;
|
||||
start += 13;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
std::size_t end = name.find_last_of('>');
|
||||
|
|
|
@ -207,9 +207,9 @@ struct pusher<function_sig<Sigs...>> {
|
|||
lua_CFunction freefunc = function_detail::call;
|
||||
|
||||
stack::push(L, userdata_value(targetdata));
|
||||
function_detail::free_function_cleanup(L);
|
||||
lua_setmetatable(L, -2);
|
||||
stack::push(L, freefunc, 1);
|
||||
function_detail::free_function_cleanup(L);
|
||||
lua_setmetatable(L, -2);
|
||||
stack::push(L, freefunc, 1);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
|
|
|
@ -40,7 +40,10 @@ struct implicit_wrapper {
|
|||
}
|
||||
};
|
||||
|
||||
const static auto& cleanup_key = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧";
|
||||
inline decltype(auto) cleanup_key() {
|
||||
const auto& name = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧";
|
||||
return name;
|
||||
}
|
||||
|
||||
template<typename T, typename Func, typename = void>
|
||||
struct functor {
|
||||
|
@ -229,8 +232,8 @@ inline int usertype_gc(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void free_function_cleanup(lua_State* L) {
|
||||
const static char* metatablename = &cleanup_key[0];
|
||||
inline void free_function_cleanup(lua_State* L) {
|
||||
const static char* metatablename = &cleanup_key()[0];
|
||||
int metapushed = luaL_newmetatable(L, metatablename);
|
||||
if (metapushed == 1) {
|
||||
stack::set_field(L, "__gc", function_detail::gc);
|
||||
|
|
|
@ -52,8 +52,15 @@ template <typename T>
|
|||
const std::size_t id_for<T>::value = unique_id();
|
||||
#endif // No Runtime Type Information / No Exceptions
|
||||
|
||||
const auto& base_class_check_key = u8"♡o。.(✿ฺ。 ✿ฺ)";
|
||||
const auto& base_class_cast_key = u8"(◕‿◕✿)";
|
||||
inline decltype(auto) base_class_check_key() {
|
||||
static const auto& key = u8"♡o。.(✿ฺ。 ✿ฺ)";
|
||||
return key;
|
||||
}
|
||||
|
||||
inline decltype(auto) base_class_cast_key() {
|
||||
static const auto& key = u8"(◕‿◕✿)";
|
||||
return key;
|
||||
}
|
||||
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ struct getter<T*> {
|
|||
|
||||
static T* get_no_nil_from(lua_State* L, void* udata, int index = -1) {
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_check_key[0]) != 0) {
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_check_key()[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
|
@ -242,7 +242,7 @@ struct getter<T*> {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key[0]) != 0) {
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
|
@ -251,7 +251,7 @@ struct getter<T*> {
|
|||
}
|
||||
#else
|
||||
// Lol, you motherfucker
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key[0]) != 0) {
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
|
@ -430,12 +430,12 @@ struct checker<T, type::userdata, C> {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
lua_getfield(L, -1, &detail::base_class_check_key[0]);
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
bool success = detail::catch_check<T>(basecast);
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
lua_getfield(L, -1, &detail::base_class_check_key[0]);
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
|
@ -445,7 +445,7 @@ struct checker<T, type::userdata, C> {
|
|||
bool success = ic(typeid(T));
|
||||
#else
|
||||
// Topkek
|
||||
lua_getfield(L, -1, &detail::base_class_check_key[0]);
|
||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||
if (stack::get<type>(L) == type::nil) {
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
|
|
|
@ -115,9 +115,9 @@ template <typename... Args>
|
|||
using has_destructor = meta::Or<is_destructor<meta::Unqualified<Args>>...>;
|
||||
|
||||
enum class stage {
|
||||
normalmeta,
|
||||
refmeta,
|
||||
uniquemeta,
|
||||
normalmeta,
|
||||
refmeta,
|
||||
uniquemeta,
|
||||
};
|
||||
|
||||
template<typename T, stage metastage>
|
||||
|
@ -127,11 +127,11 @@ inline void push_metatable(lua_State* L, bool needsindexfunction, std::vector<st
|
|||
int metatableindex = lua_gettop(L);
|
||||
if (baseclasscheck != nullptr) {
|
||||
stack::push(L, light_userdata_value(baseclasscheck));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_check_key[0]);
|
||||
lua_setfield(L, metatableindex, &detail::base_class_check_key()[0]);
|
||||
}
|
||||
if (baseclasscast != nullptr) {
|
||||
stack::push(L, light_userdata_value(baseclasscast));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_cast_key[0]);
|
||||
lua_setfield(L, metatableindex, &detail::base_class_cast_key()[0]);
|
||||
}
|
||||
if (funcs.size() < 1 && metafunctable.size() < 2) {
|
||||
return;
|
||||
|
|
85
tests.cpp
85
tests.cpp
|
@ -1520,88 +1520,3 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
|
|||
|
||||
REQUIRE_THROWS(lua.script("r:func(1,2,'meow')"));
|
||||
}
|
||||
|
||||
TEST_CASE("threading/coroutines", "ensure calling a coroutine works") {
|
||||
const auto& script = R"(counter = 20
|
||||
|
||||
function loop()
|
||||
while counter ~= 30
|
||||
do
|
||||
coroutine.yield(counter);
|
||||
counter = counter + 1;
|
||||
end
|
||||
return counter
|
||||
end
|
||||
)";
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||
lua.script(script);
|
||||
sol::coroutine cr = lua["loop"];
|
||||
|
||||
int counter;
|
||||
for (counter = 20; counter < 31 && cr; ++counter) {
|
||||
int value = cr();
|
||||
if (counter != value) {
|
||||
throw std::logic_error("fuck");
|
||||
}
|
||||
}
|
||||
counter -= 1;
|
||||
REQUIRE(counter == 30);
|
||||
}
|
||||
|
||||
TEST_CASE("threading/new-thread-coroutines", "ensure calling a coroutine works when the work is put on a different thread") {
|
||||
const auto& script = R"(counter = 20
|
||||
|
||||
function loop()
|
||||
while counter ~= 30
|
||||
do
|
||||
coroutine.yield(counter);
|
||||
counter = counter + 1;
|
||||
end
|
||||
return counter
|
||||
end
|
||||
)";
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||
lua.script(script);
|
||||
sol::thread runner = sol::thread::create(lua.lua_state());
|
||||
sol::state_view runnerstate = runner.state();
|
||||
sol::coroutine cr = runnerstate["loop"];
|
||||
|
||||
int counter;
|
||||
for (counter = 20; counter < 31 && cr; ++counter) {
|
||||
int value = cr();
|
||||
if (counter != value) {
|
||||
throw std::logic_error("fuck");
|
||||
}
|
||||
}
|
||||
counter -= 1;
|
||||
REQUIRE(counter == 30);
|
||||
}
|
||||
|
||||
TEST_CASE("issues/stack-overflow", "make sure various operations repeated don't trigger stack overflow") {
|
||||
sol::state lua;
|
||||
lua.script("t = {};t[0]=20");
|
||||
lua.script("lua_function=function(i)return i;end");
|
||||
|
||||
sol::function f = lua["lua_function"];
|
||||
std::string teststring = "testtext";
|
||||
REQUIRE_NOTHROW(
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
std::string result = f(teststring);
|
||||
if (result != teststring) throw std::logic_error("RIP");
|
||||
}
|
||||
);
|
||||
sol::table t = lua["t"];
|
||||
int expected = 20;
|
||||
REQUIRE_NOTHROW(
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
int result = t[0];
|
||||
t.size();
|
||||
if (result != expected)
|
||||
throw std::logic_error("RIP");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
64
tests_coroutines.cpp
Normal file
64
tests_coroutines.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#define SOL_CHECK_ARGUMENTS
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <sol.hpp>
|
||||
|
||||
TEST_CASE("threading/coroutines", "ensure calling a coroutine works") {
|
||||
const auto& script = R"(counter = 20
|
||||
|
||||
function loop()
|
||||
while counter ~= 30
|
||||
do
|
||||
coroutine.yield(counter);
|
||||
counter = counter + 1;
|
||||
end
|
||||
return counter
|
||||
end
|
||||
)";
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||
lua.script(script);
|
||||
sol::coroutine cr = lua["loop"];
|
||||
|
||||
int counter;
|
||||
for (counter = 20; counter < 31 && cr; ++counter) {
|
||||
int value = cr();
|
||||
if (counter != value) {
|
||||
throw std::logic_error("fuck");
|
||||
}
|
||||
}
|
||||
counter -= 1;
|
||||
REQUIRE(counter == 30);
|
||||
}
|
||||
|
||||
TEST_CASE("threading/new-thread-coroutines", "ensure calling a coroutine works when the work is put on a different thread") {
|
||||
const auto& script = R"(counter = 20
|
||||
|
||||
function loop()
|
||||
while counter ~= 30
|
||||
do
|
||||
coroutine.yield(counter);
|
||||
counter = counter + 1;
|
||||
end
|
||||
return counter
|
||||
end
|
||||
)";
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
|
||||
lua.script(script);
|
||||
sol::thread runner = sol::thread::create(lua.lua_state());
|
||||
sol::state_view runnerstate = runner.state();
|
||||
sol::coroutine cr = runnerstate["loop"];
|
||||
|
||||
int counter;
|
||||
for (counter = 20; counter < 31 && cr; ++counter) {
|
||||
int value = cr();
|
||||
if (counter != value) {
|
||||
throw std::logic_error("fuck");
|
||||
}
|
||||
}
|
||||
counter -= 1;
|
||||
REQUIRE(counter == 30);
|
||||
}
|
30
tests_overflow.cpp
Normal file
30
tests_overflow.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#define SOL_CHECK_ARGUMENTS
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <sol.hpp>
|
||||
|
||||
|
||||
TEST_CASE("issues/stack-overflow", "make sure various operations repeated don't trigger stack overflow") {
|
||||
sol::state lua;
|
||||
lua.script("t = {};t[0]=20");
|
||||
lua.script("lua_function=function(i)return i;end");
|
||||
|
||||
sol::function f = lua["lua_function"];
|
||||
std::string teststring = "testtext";
|
||||
REQUIRE_NOTHROW(
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
std::string result = f(teststring);
|
||||
if (result != teststring) throw std::logic_error("RIP");
|
||||
}
|
||||
);
|
||||
sol::table t = lua["t"];
|
||||
int expected = 20;
|
||||
REQUIRE_NOTHROW(
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
int result = t[0];
|
||||
t.size();
|
||||
if (result != expected)
|
||||
throw std::logic_error("RIP");
|
||||
}
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user