mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
formalize unsafe_function_result
add index-based getter to function_result add safety checks for double deleters and other things of that nature
This commit is contained in:
parent
e6f74b85d9
commit
10b1bb04a9
|
@ -5,7 +5,7 @@ function
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This abstraction assumes the function runs safely. If you expect your code to have errors (e.g., you don't always have explicit control over it or are trying to debug errors), please use :doc:`sol::protected_function<protected_function>` explicitly.
|
This abstraction assumes the function runs safely. If you expect your code to have errors (e.g., you don't always have explicit control over it or are trying to debug errors), please use :doc:`sol::protected_function<protected_function>` explicitly. You can also make ``sol::function`` default to ``sol::protected_function`` by turning on :ref:`the safety features<config>`.
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
@ -15,12 +15,12 @@ function
|
||||||
Function is a correct-assuming version of :doc:`protected_function<protected_function>`, omitting the need for typechecks and error handling (thus marginally increasing speed in some cases). It is the default function type of Sol. Grab a function directly off the stack using the constructor:
|
Function is a correct-assuming version of :doc:`protected_function<protected_function>`, omitting the need for typechecks and error handling (thus marginally increasing speed in some cases). It is the default function type of Sol. Grab a function directly off the stack using the constructor:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:caption: constructor: function
|
:caption: constructor: unsafe_function
|
||||||
|
|
||||||
function(lua_State* L, int index = -1);
|
unsafe_function(lua_State* L, int index = -1);
|
||||||
|
|
||||||
|
|
||||||
When called without the return types being specified by either a ``sol::types<...>`` list or a ``call<Ret...>( ... )`` template type list, it generates a :ref:`function_result<function-result>` class that gets implicitly converted to the requested return type. For example:
|
Calls the constructor and creates this type, straight from the stack. For example:
|
||||||
|
|
||||||
.. code-block:: lua
|
.. code-block:: lua
|
||||||
:caption: func_barks.lua
|
:caption: func_barks.lua
|
||||||
|
@ -44,7 +44,7 @@ The following C++ code will call this function from this file and retrieve the r
|
||||||
sol::function woof = lua["woof"];
|
sol::function woof = lua["woof"];
|
||||||
double numwoof = woof(20);
|
double numwoof = woof(20);
|
||||||
|
|
||||||
The call ``woof(20)`` generates a :ref:`function_result<function-result>`, which is then implicitly converted to an ``double`` after being called. The intermediate temporary ``function_result`` is then destructed, popping the Lua function call results off the Lua stack.
|
The call ``woof(20)`` generates a :ref:`unsafe_function_result<unsafe-function-result>`, which is then implicitly converted to an ``double`` after being called. The intermediate temporary ``function_result`` is then destructed, popping the Lua function call results off the Lua stack.
|
||||||
|
|
||||||
You can also return multiple values by using ``std::tuple``, or if you need to bind them to pre-existing variables use ``sol::tie``:
|
You can also return multiple values by using ``std::tuple``, or if you need to bind them to pre-existing variables use ``sol::tie``:
|
||||||
|
|
||||||
|
@ -67,13 +67,13 @@ This makes it much easier to work with multiple return values. Using ``std::tie`
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Do NOT save the return type of a :ref:`function_result<function-result>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. Unlike its counterpart :ref:`protected_function_result<protected-function-result>`, ``function_result`` is NOT safe to store as it assumes that its return types are still at the top of the stack and when its destructor is called will pop the number of results the function was supposed to return off the top of the stack. If you mess with the Lua stack between saving ``function_result`` and it being destructed, you will be subject to an incredible number of surprising and hard-to-track bugs. Don't do it.
|
Do NOT save the return type of a :ref:`unsafe_function_result<unsafe-function-result>` (``function_result`` when :ref:`safety configurations are not turned on<config>`) with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. Unlike its counterpart :ref:`protected_function_result<protected-function-result>`, ``function_result`` is NOT safe to store as it assumes that its return types are still at the top of the stack and when its destructor is called will pop the number of results the function was supposed to return off the top of the stack. If you mess with the Lua stack between saving ``function_result`` and it being destructed, you will be subject to an incredible number of surprising and hard-to-track bugs. Don't do it.
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:caption: function: call operator / function call
|
:caption: function: call operator / function call
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
function_result operator()( Args&&... args );
|
unsafe_function_result operator()( Args&&... args );
|
||||||
|
|
||||||
template<typename... Ret, typename... Args>
|
template<typename... Ret, typename... Args>
|
||||||
decltype(auto) call( Args&&... args );
|
decltype(auto) call( Args&&... args );
|
||||||
|
@ -81,7 +81,7 @@ This makes it much easier to work with multiple return values. Using ``std::tie`
|
||||||
template<typename... Ret, typename... Args>
|
template<typename... Ret, typename... Args>
|
||||||
decltype(auto) operator()( types<Ret...>, Args&&... 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 a detectable error does occur, and otherwise can return garbage / bogus values if the user is not careful.
|
||||||
|
|
||||||
|
|
||||||
To know more about how function arguments are handled, see :ref:`this note<function-argument-handling>`
|
To know more about how function arguments are handled, see :ref:`this note<function-argument-handling>`
|
||||||
|
|
|
@ -95,7 +95,7 @@ Alternatively, with a bad or good function call, you can use ``sol::optional`` t
|
||||||
// No value!
|
// No value!
|
||||||
}
|
}
|
||||||
|
|
||||||
That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::function_result`` type that comes from calling :doc:`sol::function<function>`.
|
That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::unsafe_function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::unsafe_function_result`` type that comes from calling :doc:`sol::unsafe_function<function>`.
|
||||||
|
|
||||||
If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on:
|
If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on:
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
proxy, (protected\_)function_result - proxy_base derivatives
|
proxy, (protected\unsafe)_function_result - proxy_base derivatives
|
||||||
============================================================
|
==================================================================
|
||||||
*``table[x]`` and ``function(...)`` conversion struct*
|
*``table[x]`` and ``function(...)`` conversion struct*
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ proxy, (protected\_)function_result - proxy_base derivatives
|
||||||
|
|
||||||
struct stack_proxy: proxy_base<...>;
|
struct stack_proxy: proxy_base<...>;
|
||||||
|
|
||||||
struct function_result : proxy_base<...>;
|
struct unsafe_function_result : proxy_base<...>;
|
||||||
|
|
||||||
struct protected_function_result: proxy_base<...>;
|
struct protected_function_result: proxy_base<...>;
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ Returns whether this proxy actually refers to a valid object. It uses :ref:`sol:
|
||||||
template <typename Fx>
|
template <typename Fx>
|
||||||
proxy& operator=( Fx&& function );
|
proxy& operator=( Fx&& function );
|
||||||
|
|
||||||
Sets the value associated with the keys the proxy was generated with to ``value``. If this is a function, calls ``set_function``. If it is not, just calls ``set``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`. See :ref:`note<note 1>` for caveats.
|
Sets the value associated with the keys the proxy was generated with to ``value``. If this is a function, calls ``set_function``. If it is not, just calls ``set``. Does not exist on :ref:`unsage_function_result<unsafe-function-result>` or :ref:`protected_function_result<protected-function-result>`. See :ref:`note<note 1>` for caveats.
|
||||||
|
|
||||||
.. code-block:: c++
|
.. code-block:: c++
|
||||||
:caption: function: set a callable
|
:caption: function: set a callable
|
||||||
|
@ -142,7 +142,7 @@ Sets the value associated with the keys the proxy was generated with to ``value`
|
||||||
template <typename Fx>
|
template <typename Fx>
|
||||||
proxy& set_function( Fx&& fx );
|
proxy& set_function( Fx&& fx );
|
||||||
|
|
||||||
Sets the value associated with the keys the proxy was generated with to a function ``fx``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`.
|
Sets the value associated with the keys the proxy was generated with to a function ``fx``. Does not exist on :ref:`unsafe_function_result<unsafe-function-result>` or :ref:`protected_function_result<protected-function-result>`.
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: c++
|
.. code-block:: c++
|
||||||
|
@ -152,29 +152,33 @@ Sets the value associated with the keys the proxy was generated with to a functi
|
||||||
template <typename T>
|
template <typename T>
|
||||||
proxy& set( T&& value );
|
proxy& set( T&& value );
|
||||||
|
|
||||||
Sets the value associated with the keys the proxy was generated with to ``value``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`.
|
Sets the value associated with the keys the proxy was generated with to ``value``. Does not exist on :ref:`unsafe_function_result<unsafe-function-result>` or :ref:`protected_function_result<protected-function-result>`.
|
||||||
|
|
||||||
stack_proxy
|
stack_proxy
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
``sol::stack_proxy`` is what gets returned by :doc:`sol::variadic_args<variadic_args>` and other parts of the framework. It is similar to proxy, but is meant to alias a stack index and not a named variable.
|
``sol::stack_proxy`` is what gets returned by :doc:`sol::variadic_args<variadic_args>` and other parts of the framework. It is similar to proxy, but is meant to alias a stack index and not a named variable.
|
||||||
|
|
||||||
.. _function-result:
|
.. _unsafe-function-result:
|
||||||
|
|
||||||
function_result
|
unsafe_function_result
|
||||||
---------------
|
----------------------
|
||||||
|
|
||||||
``function_result`` is a temporary-only, intermediate-only implicit conversion worker for when :doc:`function<function>` is called. It is *NOT* meant to be stored or captured with ``auto``. It provides fast access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=``, as is present on :ref:`proxy<proxy>`.
|
``unsafe_function_result`` is a temporary-only, intermediate-only implicit conversion worker for when :doc:`function<function>` is called. It is *NOT* meant to be stored or captured with ``auto``. It provides fast access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=``, as is present on :ref:`proxy<proxy>`.
|
||||||
|
|
||||||
|
|
||||||
|
This type does, however, allow access to multiple underlying values. Use ``result.get<Type>(index_offset)`` to retrieve an object of ``Type`` at an offset of ``index_offset`` in the results. Offset is 0 based. Not specifying an argument defaults the value to 0.
|
||||||
|
|
||||||
.. _protected-function-result:
|
.. _protected-function-result:
|
||||||
|
|
||||||
protected_function_result
|
protected_function_result
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
``protected_function_result`` is a nicer version of ``function_result`` that can be used to detect errors. Its gives safe access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=`` as is present on :ref:`proxy<proxy>`.
|
``protected_function_result`` is a nicer version of ``unsafe_function_result`` that can be used to detect errors. Its gives safe access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=`` as is present on :ref:`proxy<proxy>`.
|
||||||
|
|
||||||
|
|
||||||
|
This type does, however, allow access to multiple underlying values. Use ``result.get<Type>(index_offset)`` to retrieve an object of ``Type`` at an offset of ``index_offset`` in the results. Offset is 0 based. Not specifying an argument defaults the value to 0.
|
||||||
|
|
||||||
.. _note 1:
|
.. _note 1:
|
||||||
|
|
||||||
on function objects and proxies
|
on function objects and proxies
|
||||||
|
|
|
@ -88,7 +88,7 @@ If you need safety, please use the version of these functions with ``safe`` (suc
|
||||||
|
|
||||||
These functions run the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run isolated: any scripts or code run will affect code in the ``lua_State*`` the object uses as well (unless ``local`` is applied to a variable declaration, as specified by the Lua language). Code ran in this fashion is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques.
|
These functions run the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run isolated: any scripts or code run will affect code in the ``lua_State*`` the object uses as well (unless ``local`` is applied to a variable declaration, as specified by the Lua language). Code ran in this fashion is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques.
|
||||||
|
|
||||||
If your script returns a value, you can capture it from the returned :ref:`sol::function_result<function-result>`/:ref:`sol::protected_function_result<protected-function-result>`. Note that the plain versions that do not take an environment or a callback function assume that the contents internally not only loaded properly but ran to completion without errors, for the sake of simplicity and performance.
|
If your script returns a value, you can capture it from the returned :ref:`sol::unsafe_function_result<unsafe-function-result>`/:ref:`sol::protected_function_result<protected-function-result>`. Note that the plain versions that do not take an environment or a callback function assume that the contents internally not only loaded properly but ran to completion without errors, for the sake of simplicity and performance.
|
||||||
|
|
||||||
To handle errors when using the second overload, provide a callable function/object that takes a ``lua_State*`` as its first argument and a ``sol::protected_function_result`` as its second argument. ``sol::script_default_on_error`` and ``sol::script_pass_on_error`` are 2 functions provided by sol that will either generate a traceback error to return / throw (if throwing is allowed); or, pass the error on through and return it to the user (respectively). An example of having your:
|
To handle errors when using the second overload, provide a callable function/object that takes a ``lua_State*`` as its first argument and a ``sol::protected_function_result`` as its second argument. ``sol::script_default_on_error`` and ``sol::script_pass_on_error`` are 2 functions provided by sol that will either generate a traceback error to return / throw (if throwing is allowed); or, pass the error on through and return it to the user (respectively). An example of having your:
|
||||||
|
|
||||||
|
|
|
@ -91,4 +91,4 @@ As a side note, binding functions with default parameters does not magically bin
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Do **NOT** save the return type of a :ref:`function_result<function-result>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere unless you are exactly aware of the consequences of messing with the stack. See :ref:`here<function-result-warning>` for more information.
|
Do **NOT** save the return type of a :ref:`unsafe_function_result<unsafe-function-result>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere unless you are exactly aware of the consequences of messing with the stack. See :ref:`here<function-result-warning>` for more information.
|
||||||
|
|
74
examples/indirect_function_calls.cpp
Normal file
74
examples/indirect_function_calls.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS 1
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
sol::variadic_results call_it(sol::object function_name, sol::variadic_args args, sol::this_environment env, sol::this_state L) {
|
||||||
|
sol::state_view lua = L;
|
||||||
|
// default to global table as environment
|
||||||
|
sol::environment function_environment = lua.globals();
|
||||||
|
if (env) {
|
||||||
|
// if we have an environment, use that instead
|
||||||
|
function_environment = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get and call the function
|
||||||
|
sol::protected_function pf = function_environment[function_name];
|
||||||
|
sol::protected_function_result res = pf(args);
|
||||||
|
|
||||||
|
//
|
||||||
|
sol::variadic_results results;
|
||||||
|
if (!res.valid()) {
|
||||||
|
// something went wrong: log/crash/whatever
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
int returncount = res.return_count();
|
||||||
|
for (int i = 0; i < returncount; i++) {
|
||||||
|
// pass offset to get the object that was returned
|
||||||
|
sol::object obj = res.get<sol::object>(i);
|
||||||
|
results.push_back(obj);
|
||||||
|
}
|
||||||
|
// return the results
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== indirect function calls example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua["call_it"] = call_it;
|
||||||
|
|
||||||
|
// some functions to call
|
||||||
|
lua.script(R"(
|
||||||
|
function add (a, b)
|
||||||
|
return a + b;
|
||||||
|
end
|
||||||
|
|
||||||
|
function subtract (a, b)
|
||||||
|
return a - b;
|
||||||
|
end
|
||||||
|
|
||||||
|
function log (x)
|
||||||
|
print(x)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
// call the functions indirectly, using a name
|
||||||
|
lua.script(R"(
|
||||||
|
call_it("log", "hiyo")
|
||||||
|
call_it("log", 24)
|
||||||
|
subtract_result = call_it("subtract", 5, 1)
|
||||||
|
add_result = call_it("add", 5, 1)
|
||||||
|
)");
|
||||||
|
|
||||||
|
int subtract_result = lua["subtract_result"];
|
||||||
|
int add_result = lua["add_result"];
|
||||||
|
|
||||||
|
assert(add_result == 6);
|
||||||
|
assert(subtract_result == 4);
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -79,7 +79,7 @@ namespace sol {
|
||||||
using main_protected_function = main_safe_function;
|
using main_protected_function = main_safe_function;
|
||||||
using stack_protected_function = stack_safe_function;
|
using stack_protected_function = stack_safe_function;
|
||||||
using stack_aligned_protected_function = stack_aligned_safe_function;
|
using stack_aligned_protected_function = stack_aligned_safe_function;
|
||||||
#ifdef SOL_SAFE_FUNCTIONS
|
#ifdef SOL_SAFE_FUNCTION
|
||||||
using function = protected_function;
|
using function = protected_function;
|
||||||
using main_function = main_protected_function;
|
using main_function = main_protected_function;
|
||||||
using stack_function = stack_protected_function;
|
using stack_function = stack_protected_function;
|
||||||
|
@ -92,10 +92,14 @@ namespace sol {
|
||||||
#endif
|
#endif
|
||||||
using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>;
|
using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>;
|
||||||
|
|
||||||
struct function_result;
|
struct unsafe_function_result;
|
||||||
struct protected_function_result;
|
struct protected_function_result;
|
||||||
using safe_function_result = protected_function_result;
|
using safe_function_result = protected_function_result;
|
||||||
using unsafe_function_result = function_result;
|
#ifdef SOL_SAFE_FUNCTION
|
||||||
|
using function_result = safe_function_result;
|
||||||
|
#else
|
||||||
|
using function_result = unsafe_function_result;
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename base_t>
|
template <typename base_t>
|
||||||
class basic_object;
|
class basic_object;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
inline protected_function_result::protected_function_result(function_result&& o) noexcept
|
inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept
|
||||||
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
|
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
|
||||||
// Must be manual, otherwise destructor will screw us
|
// Must be manual, otherwise destructor will screw us
|
||||||
// return count being 0 is enough to keep things clean
|
// return count being 0 is enough to keep things clean
|
||||||
|
@ -37,7 +37,7 @@ namespace sol {
|
||||||
o.abandon();
|
o.abandon();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline protected_function_result& protected_function_result::operator=(function_result&& o) noexcept {
|
inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept {
|
||||||
L = o.lua_state();
|
L = o.lua_state();
|
||||||
index = o.stack_index();
|
index = o.stack_index();
|
||||||
returncount = o.return_count();
|
returncount = o.return_count();
|
||||||
|
@ -50,14 +50,14 @@ namespace sol {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function_result::function_result(protected_function_result&& o) noexcept
|
inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept
|
||||||
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
|
: L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
|
||||||
// Must be manual, otherwise destructor will screw us
|
// Must be manual, otherwise destructor will screw us
|
||||||
// return count being 0 is enough to keep things clean
|
// return count being 0 is enough to keep things clean
|
||||||
// but we will be thorough
|
// but we will be thorough
|
||||||
o.abandon();
|
o.abandon();
|
||||||
}
|
}
|
||||||
inline function_result& function_result::operator=(protected_function_result&& o) noexcept {
|
inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept {
|
||||||
L = o.lua_state();
|
L = o.lua_state();
|
||||||
index = o.stack_index();
|
index = o.stack_index();
|
||||||
returncount = o.return_count();
|
returncount = o.return_count();
|
||||||
|
|
|
@ -22,94 +22,7 @@
|
||||||
#ifndef SOL_FUNCTION_RESULT_HPP
|
#ifndef SOL_FUNCTION_RESULT_HPP
|
||||||
#define SOL_FUNCTION_RESULT_HPP
|
#define SOL_FUNCTION_RESULT_HPP
|
||||||
|
|
||||||
#include "reference.hpp"
|
#include "protected_function_result.hpp"
|
||||||
#include "tuple.hpp"
|
#include "unsafe_function_result.hpp"
|
||||||
#include "stack.hpp"
|
|
||||||
#include "proxy_base.hpp"
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace sol {
|
|
||||||
struct function_result : public proxy_base<function_result> {
|
|
||||||
private:
|
|
||||||
lua_State* L;
|
|
||||||
int index;
|
|
||||||
int returncount;
|
|
||||||
|
|
||||||
public:
|
|
||||||
function_result() = default;
|
|
||||||
function_result(lua_State* Ls, int idx = -1, int retnum = 0)
|
|
||||||
: L(Ls), index(idx), returncount(retnum) {
|
|
||||||
}
|
|
||||||
function_result(const function_result&) = default;
|
|
||||||
function_result& operator=(const function_result&) = default;
|
|
||||||
function_result(function_result&& o)
|
|
||||||
: L(o.L), index(o.index), returncount(o.returncount) {
|
|
||||||
// Must be manual, otherwise destructor will screw us
|
|
||||||
// return count being 0 is enough to keep things clean
|
|
||||||
// but will be thorough
|
|
||||||
o.abandon();
|
|
||||||
}
|
|
||||||
function_result& operator=(function_result&& o) {
|
|
||||||
L = o.L;
|
|
||||||
index = o.index;
|
|
||||||
returncount = o.returncount;
|
|
||||||
// Must be manual, otherwise destructor will screw us
|
|
||||||
// return count being 0 is enough to keep things clean
|
|
||||||
// but will be thorough
|
|
||||||
o.abandon();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function_result(const protected_function_result& o) = delete;
|
|
||||||
function_result& operator=(const protected_function_result& o) = delete;
|
|
||||||
function_result(protected_function_result&& o) noexcept;
|
|
||||||
function_result& operator=(protected_function_result&& o) noexcept;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
decltype(auto) get() const {
|
|
||||||
return stack::get<T>(L, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
call_status status() const noexcept {
|
|
||||||
return call_status::ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid() const noexcept {
|
|
||||||
return status() == call_status::ok || status() == call_status::yielded;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_State* lua_state() const {
|
|
||||||
return L;
|
|
||||||
};
|
|
||||||
int stack_index() const {
|
|
||||||
return index;
|
|
||||||
};
|
|
||||||
int return_count() const {
|
|
||||||
return returncount;
|
|
||||||
};
|
|
||||||
void abandon() noexcept {
|
|
||||||
//L = nullptr;
|
|
||||||
index = 0;
|
|
||||||
returncount = 0;
|
|
||||||
}
|
|
||||||
~function_result() {
|
|
||||||
lua_pop(L, returncount);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace stack {
|
|
||||||
template <>
|
|
||||||
struct pusher<function_result> {
|
|
||||||
static int push(lua_State* L, const function_result& fr) {
|
|
||||||
int p = 0;
|
|
||||||
for (int i = 0; i < fr.return_count(); ++i) {
|
|
||||||
lua_pushvalue(L, i + fr.stack_index());
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace stack
|
|
||||||
} // namespace sol
|
|
||||||
|
|
||||||
#endif // SOL_FUNCTION_RESULT_HPP
|
#endif // SOL_FUNCTION_RESULT_HPP
|
||||||
|
|
|
@ -38,37 +38,43 @@ namespace sol {
|
||||||
call_status err;
|
call_status err;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
decltype(auto) tagged_get(types<optional<T>>) const {
|
decltype(auto) tagged_get(types<optional<T>>, int index_offset) const {
|
||||||
|
int target = index + index_offset;
|
||||||
if (!valid()) {
|
if (!valid()) {
|
||||||
return optional<T>(nullopt);
|
return optional<T>(nullopt);
|
||||||
}
|
}
|
||||||
return stack::get<optional<T>>(L, index);
|
return stack::get<optional<T>>(L, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
decltype(auto) tagged_get(types<T>) const {
|
decltype(auto) tagged_get(types<T>, int index_offset) const {
|
||||||
|
int target = index + index_offset;
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
if (!valid()) {
|
if (!valid()) {
|
||||||
type_panic_c_str(L, index, type_of(L, index), type::none, "bad get from protected_function_result (is not an error)");
|
type t = type_of(L, target);
|
||||||
|
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)");
|
||||||
}
|
}
|
||||||
#endif // Check Argument Safety
|
#endif // Check Argument Safety
|
||||||
return stack::get<T>(L, index);
|
return stack::get<T>(L, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<error> tagged_get(types<optional<error>>) const {
|
optional<error> tagged_get(types<optional<error>>, int index_offset) const {
|
||||||
|
int target = index + index_offset;
|
||||||
if (valid()) {
|
if (valid()) {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
return error(detail::direct_error, stack::get<std::string>(L, index));
|
return error(detail::direct_error, stack::get<std::string>(L, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
error tagged_get(types<error>) const {
|
error tagged_get(types<error>, int index_offset) const {
|
||||||
|
int target = index + index_offset;
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
if (valid()) {
|
if (valid()) {
|
||||||
type_panic_c_str(L, index, type_of(L, index), type::none, "bad get from protected_function_result (is an error)");
|
type t = type_of(L, target);
|
||||||
|
type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)");
|
||||||
}
|
}
|
||||||
#endif // Check Argument Safety
|
#endif // Check Argument Safety
|
||||||
return error(detail::direct_error, stack::get<std::string>(L, index));
|
return error(detail::direct_error, stack::get<std::string>(L, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -98,10 +104,10 @@ namespace sol {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected_function_result(const function_result& o) = delete;
|
protected_function_result(const unsafe_function_result& o) = delete;
|
||||||
protected_function_result& operator=(const function_result& o) = delete;
|
protected_function_result& operator=(const unsafe_function_result& o) = delete;
|
||||||
protected_function_result(function_result&& o) noexcept;
|
protected_function_result(unsafe_function_result&& o) noexcept;
|
||||||
protected_function_result& operator=(function_result&& o) noexcept;
|
protected_function_result& operator=(unsafe_function_result&& o) noexcept;
|
||||||
|
|
||||||
call_status status() const noexcept {
|
call_status status() const noexcept {
|
||||||
return err;
|
return err;
|
||||||
|
@ -112,8 +118,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
decltype(auto) get() const {
|
decltype(auto) get(int index_offset = 0) const {
|
||||||
return tagged_get(types<meta::unqualified_t<T>>());
|
return tagged_get(types<meta::unqualified_t<T>>(), index_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* lua_state() const noexcept {
|
lua_State* lua_state() const noexcept {
|
||||||
|
|
|
@ -422,14 +422,55 @@ namespace sol {
|
||||||
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
||||||
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
||||||
|
|
||||||
auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) {
|
auto safety_check = [&](const std::string& first) {
|
||||||
meta_function mf = meta_function::construct;
|
for (std::size_t j = 0; j < properties.size(); ++j) {
|
||||||
for (std::size_t j = 1; j < properties.size(); ++j) {
|
meta_function mf = static_cast<meta_function>(j);
|
||||||
mf = static_cast<meta_function>(j);
|
|
||||||
const std::string& mfname = to_string(mf);
|
const std::string& mfname = to_string(mf);
|
||||||
|
bool& prop = properties[j];
|
||||||
|
if (mfname != first)
|
||||||
|
continue;
|
||||||
|
switch (mf) {
|
||||||
|
case meta_function::construct:
|
||||||
|
if (prop) {
|
||||||
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
|
throw error(
|
||||||
|
#else
|
||||||
|
assert(false &&
|
||||||
|
#endif
|
||||||
|
"sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case meta_function::garbage_collect:
|
||||||
|
if (prop) {
|
||||||
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
|
throw error(
|
||||||
|
#else
|
||||||
|
assert(false &&
|
||||||
|
#endif
|
||||||
|
"sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto& kvp : varmap.functions) {
|
||||||
|
auto& first = std::get<0>(kvp);
|
||||||
|
safety_check(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) {
|
||||||
|
meta_function mf = meta_function::construct;
|
||||||
|
for (std::size_t j = 0; j < properties.size(); ++j) {
|
||||||
|
mf = static_cast<meta_function>(j);
|
||||||
|
const std::string& mfname = to_string(mf);
|
||||||
|
bool& prop = properties[j];
|
||||||
if (mfname != first)
|
if (mfname != first)
|
||||||
continue;
|
continue;
|
||||||
properties[j] = true;
|
|
||||||
switch (mf) {
|
switch (mf) {
|
||||||
case meta_function::index:
|
case meta_function::index:
|
||||||
umx.indexfunc = second;
|
umx.indexfunc = second;
|
||||||
|
@ -440,6 +481,7 @@ namespace sol {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
prop = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (meta_index) {
|
switch (meta_index) {
|
||||||
|
|
|
@ -232,7 +232,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
|
inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
|
||||||
#ifdef SOL_LUAJIT
|
#if defined(SOL_LUAJIT) && !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION)
|
||||||
if (L == nullptr) {
|
if (L == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace sol {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <>
|
template <>
|
||||||
struct is_speshul<function_result> : std::true_type {};
|
struct is_speshul<unsafe_function_result> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_speshul<protected_function_result> : std::true_type {};
|
struct is_speshul<protected_function_result> : std::true_type {};
|
||||||
|
|
||||||
|
@ -121,15 +121,15 @@ namespace sol {
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct tie_size<function_result> : std::integral_constant<std::size_t, SIZE_MAX> {};
|
struct tie_size<unsafe_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {};
|
||||||
|
|
||||||
template <std::size_t I>
|
template <std::size_t I>
|
||||||
stack_proxy get(const function_result& fr) {
|
stack_proxy get(const unsafe_function_result& fr) {
|
||||||
return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I));
|
return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t I, typename... Args>
|
template <std::size_t I, typename... Args>
|
||||||
stack_proxy get(types<Args...> t, const function_result& fr) {
|
stack_proxy get(types<Args...> t, const unsafe_function_result& fr) {
|
||||||
return detail::get(t, index_value<I>(), index_value<0>(), fr);
|
return detail::get(t, index_value<I>(), index_value<0>(), fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
function_result unsafe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
unsafe_function_result unsafe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
||||||
detail::typical_chunk_name_t basechunkname = {};
|
detail::typical_chunk_name_t basechunkname = {};
|
||||||
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
|
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
|
||||||
int index = lua_gettop(L);
|
int index = lua_gettop(L);
|
||||||
|
@ -390,19 +390,19 @@ namespace sol {
|
||||||
}
|
}
|
||||||
int postindex = lua_gettop(L);
|
int postindex = lua_gettop(L);
|
||||||
int returns = postindex - index;
|
int returns = postindex - index;
|
||||||
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result unsafe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
unsafe_function_result unsafe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
||||||
int index = lua_gettop(L);
|
int index = lua_gettop(L);
|
||||||
stack::script(L, code, chunkname, mode);
|
stack::script(L, code, chunkname, mode);
|
||||||
int postindex = lua_gettop(L);
|
int postindex = lua_gettop(L);
|
||||||
int returns = postindex - index;
|
int returns = postindex - index;
|
||||||
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
|
unsafe_function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
|
||||||
int index = lua_gettop(L);
|
int index = lua_gettop(L);
|
||||||
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
|
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
|
||||||
lua_error(L);
|
lua_error(L);
|
||||||
|
@ -413,15 +413,15 @@ namespace sol {
|
||||||
}
|
}
|
||||||
int postindex = lua_gettop(L);
|
int postindex = lua_gettop(L);
|
||||||
int returns = postindex - index;
|
int returns = postindex - index;
|
||||||
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
|
unsafe_function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
|
||||||
int index = lua_gettop(L);
|
int index = lua_gettop(L);
|
||||||
stack::script_file(L, filename, mode);
|
stack::script_file(L, filename, mode);
|
||||||
int postindex = lua_gettop(L);
|
int postindex = lua_gettop(L);
|
||||||
int returns = postindex - index;
|
int returns = postindex - index;
|
||||||
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
|
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
|
||||||
|
@ -452,7 +452,7 @@ namespace sol {
|
||||||
return safe_script_file(filename, env, script_default_on_error, mode);
|
return safe_script_file(filename, env, script_default_on_error, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOL_SAFE_FUNCTIONS
|
#ifdef SOL_SAFE_FUNCTION
|
||||||
protected_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
protected_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
||||||
return safe_script(code, chunkname, mode);
|
return safe_script(code, chunkname, mode);
|
||||||
}
|
}
|
||||||
|
@ -461,11 +461,11 @@ namespace sol {
|
||||||
return safe_script_file(filename, mode);
|
return safe_script_file(filename, mode);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
unsafe_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
|
||||||
return unsafe_script(code, chunkname, mode);
|
return unsafe_script(code, chunkname, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
|
unsafe_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) {
|
||||||
return unsafe_script_file(filename, mode);
|
return unsafe_script_file(filename, mode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1085,7 +1085,7 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_primitive<T*> : std::true_type {};
|
struct is_lua_primitive<T*> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_lua_primitive<function_result> : std::true_type {};
|
struct is_lua_primitive<unsafe_function_result> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_lua_primitive<protected_function_result> : std::true_type {};
|
struct is_lua_primitive<protected_function_result> : std::true_type {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -53,13 +53,13 @@ namespace sol {
|
||||||
luacall(n, 0);
|
luacall(n, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const {
|
unsafe_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const {
|
||||||
int stacksize = lua_gettop(lua_state());
|
int stacksize = lua_gettop(lua_state());
|
||||||
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
|
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
|
||||||
luacall(n, LUA_MULTRET);
|
luacall(n, LUA_MULTRET);
|
||||||
int poststacksize = lua_gettop(lua_state());
|
int poststacksize = lua_gettop(lua_state());
|
||||||
int returncount = poststacksize - (firstreturn - 1);
|
int returncount = poststacksize - (firstreturn - 1);
|
||||||
return function_result(lua_state(), firstreturn, returncount);
|
return unsafe_function_result(lua_state(), firstreturn, returncount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -113,7 +113,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
function_result operator()(Args&&... args) const {
|
unsafe_function_result operator()(Args&&... args) const {
|
||||||
return call<>(std::forward<Args>(args)...);
|
return call<>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
115
sol/unsafe_function_result.hpp
Normal file
115
sol/unsafe_function_result.hpp
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2017 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.
|
||||||
|
|
||||||
|
#ifndef SOL_UNSAFE_FUNCTION_RESULT_HPP
|
||||||
|
#define SOL_UNSAFE_FUNCTION_RESULT_HPP
|
||||||
|
|
||||||
|
#include "reference.hpp"
|
||||||
|
#include "tuple.hpp"
|
||||||
|
#include "stack.hpp"
|
||||||
|
#include "proxy_base.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
struct unsafe_function_result : public proxy_base<unsafe_function_result> {
|
||||||
|
private:
|
||||||
|
lua_State* L;
|
||||||
|
int index;
|
||||||
|
int returncount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsafe_function_result() = default;
|
||||||
|
unsafe_function_result(lua_State* Ls, int idx = -1, int retnum = 0)
|
||||||
|
: L(Ls), index(idx), returncount(retnum) {
|
||||||
|
}
|
||||||
|
unsafe_function_result(const unsafe_function_result&) = default;
|
||||||
|
unsafe_function_result& operator=(const unsafe_function_result&) = default;
|
||||||
|
unsafe_function_result(unsafe_function_result&& o)
|
||||||
|
: L(o.L), index(o.index), returncount(o.returncount) {
|
||||||
|
// Must be manual, otherwise destructor will screw us
|
||||||
|
// return count being 0 is enough to keep things clean
|
||||||
|
// but will be thorough
|
||||||
|
o.abandon();
|
||||||
|
}
|
||||||
|
unsafe_function_result& operator=(unsafe_function_result&& o) {
|
||||||
|
L = o.L;
|
||||||
|
index = o.index;
|
||||||
|
returncount = o.returncount;
|
||||||
|
// Must be manual, otherwise destructor will screw us
|
||||||
|
// return count being 0 is enough to keep things clean
|
||||||
|
// but will be thorough
|
||||||
|
o.abandon();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_function_result(const protected_function_result& o) = delete;
|
||||||
|
unsafe_function_result& operator=(const protected_function_result& o) = delete;
|
||||||
|
unsafe_function_result(protected_function_result&& o) noexcept;
|
||||||
|
unsafe_function_result& operator=(protected_function_result&& o) noexcept;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
decltype(auto) get(int index_offset = 0) const {
|
||||||
|
return stack::get<T>(L, index + index_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_status status() const noexcept {
|
||||||
|
return call_status::ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const noexcept {
|
||||||
|
return status() == call_status::ok || status() == call_status::yielded;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State* lua_state() const {
|
||||||
|
return L;
|
||||||
|
};
|
||||||
|
int stack_index() const {
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
int return_count() const {
|
||||||
|
return returncount;
|
||||||
|
};
|
||||||
|
void abandon() noexcept {
|
||||||
|
//L = nullptr;
|
||||||
|
index = 0;
|
||||||
|
returncount = 0;
|
||||||
|
}
|
||||||
|
~unsafe_function_result() {
|
||||||
|
lua_pop(L, returncount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace stack {
|
||||||
|
template <>
|
||||||
|
struct pusher<unsafe_function_result> {
|
||||||
|
static int push(lua_State* L, const unsafe_function_result& fr) {
|
||||||
|
int p = 0;
|
||||||
|
for (int i = 0; i < fr.return_count(); ++i) {
|
||||||
|
lua_pushvalue(L, i + fr.stack_index());
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace stack
|
||||||
|
} // namespace sol
|
||||||
|
|
||||||
|
#endif // SOL_UNSAFE_FUNCTION_RESULT_HPP
|
|
@ -460,35 +460,47 @@ namespace sol {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>());
|
luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>());
|
||||||
for (std::size_t i = 1; i < properties.size(); ++i) {
|
for (std::size_t i = 0; i < properties.size(); ++i) {
|
||||||
meta_function mf = static_cast<meta_function>(i);
|
meta_function mf = static_cast<meta_function>(i);
|
||||||
|
bool& prop = properties[i];
|
||||||
const std::string& mfname = to_string(mf);
|
const std::string& mfname = to_string(mf);
|
||||||
if (mfname == reg.name) {
|
if (mfname == reg.name) {
|
||||||
switch (mf) {
|
switch (mf) {
|
||||||
|
case meta_function::construct:
|
||||||
|
if (prop) {
|
||||||
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
|
throw error(
|
||||||
|
#else
|
||||||
|
assert(false &&
|
||||||
|
#endif
|
||||||
|
"sol: 2 separate constructor (new) functions were set on this type. Please specify only 1 sol::meta_function::construct/'new' type AND wrap the function in a sol::factories/initializers call, as shown by the documentation and examples, otherwise you may create problems");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case meta_function::garbage_collect:
|
case meta_function::garbage_collect:
|
||||||
if (destructfunc != nullptr) {
|
if (destructfunc != nullptr) {
|
||||||
#ifdef SOL_NO_EXCEPTIONS
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
throw error("sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
|
throw error(
|
||||||
#else
|
#else
|
||||||
assert(false && "sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
|
assert(false &&
|
||||||
#endif
|
#endif
|
||||||
|
"sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
|
||||||
}
|
}
|
||||||
destructfunc = reg.func;
|
destructfunc = reg.func;
|
||||||
return;
|
return;
|
||||||
case meta_function::index:
|
case meta_function::index:
|
||||||
indexfunc = reg.func;
|
indexfunc = reg.func;
|
||||||
mustindex = true;
|
mustindex = true;
|
||||||
properties[i] = true;
|
prop = true;
|
||||||
return;
|
return;
|
||||||
case meta_function::new_index:
|
case meta_function::new_index:
|
||||||
newindexfunc = reg.func;
|
newindexfunc = reg.func;
|
||||||
mustindex = true;
|
mustindex = true;
|
||||||
properties[i] = true;
|
prop = true;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
properties[i] = true;
|
prop = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -653,7 +653,7 @@ TEST_CASE("state/script return converts", "make sure that script return values a
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
sol::protected_function_result r1 = lua.unsafe_script("return 2");
|
sol::protected_function_result r1 = lua.unsafe_script("return 2");
|
||||||
sol::function_result r2 = lua.safe_script("return 3");
|
sol::unsafe_function_result r2 = lua.safe_script("return 3");
|
||||||
|
|
||||||
int v1 = r1;
|
int v1 = r1;
|
||||||
int v2 = r2;
|
int v2 = r2;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user