add constructors and assignment operators for protected function results and the like

improve documentation about saving compilation time and space
add docs about the two `script_..._error` functions
update single
This commit is contained in:
ThePhD 2017-08-27 00:05:35 -04:00
parent 626da4db5a
commit a39679293c
8 changed files with 151 additions and 24 deletions

View File

@ -75,13 +75,13 @@ This function takes a number of :ref:`sol::lib<lib-enum>` as arguments and opens
template <typename ErrorFunc>
protected_function_result script_file(const std::string& filename, const environment& env, ErrorFunc&& on_error, load_mode mode = load_mode::any);
If you need safety, please use the version of these functions with ``safe_script(_file)`` appended in front of them. They will always check for errors and always return a ``sol::protected_function_result``. If you explicitly do not want to check for errors and want to simply invoke ``lua_error`` in the case of errors, use ``unsafe_script(_file)`` versions.
If you need safety, please use the version of these functions with ``safe`` (such as ``safe_script(_file)``) appended in front of them. They will always check for errors and always return a ``sol::protected_function_result``. If you explicitly do not want to check for errors and want to simply invoke ``lua_error`` in the case of errors (which will call ``panic``), use ``unsafe_script(_file)`` versions.
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.
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. Then, handle the errors any way you like:
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 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). Then, handle the errors any way you like:
.. code-block:: cpp
:caption: running code safely

View File

@ -67,18 +67,6 @@ We support:
* LuaJIT 2.1.x-beta3+
"compiler out of heap space"
----------------------------
Typical of Visual Studio, the compiler will complain that it is out of heap space because Visual Studio defaults to using the x86 (32-bit) version of itself (it will still compile x86 or x64 or ARM binaries, just the compiler **itself** is a 32-bit executable). In order to get around heap space requirements, add the following statement in your ``.vcoxproj`` files under the ``<Import .../>`` statement, as instructed by `OrfeasZ in this issue`_::
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
This should use the 64-bit tools by default, and increase your maximum heap space to whatever a 64-bit windows machine can handle.
binary sizes
------------
@ -107,7 +95,7 @@ The next step for Sol from a developer standpoint is to formally make the librar
Hopefully, as things progress, we move things forward.
.. _sol2 release v2.18.0: https://github.com/ThePhD/sol2/releases/tag/v2.18.1
.. _sol2 release v2.18.1: https://github.com/ThePhD/sol2/releases/tag/v2.18.1
.. _OrfeasZ in this issue: https://github.com/ThePhD/sol2/issues/329#issuecomment-276824983
.. _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

@ -8,7 +8,7 @@ Here is some advice and some tricks for common errors about iteration, compile t
Running Scripts
---------------
Scripts can have syntax errors, can load from the file system wrong, or have runtime issues. Knowing which one can be troublesome. There are various small building blocks to load and run code, but to check errors you can use the overloaded :ref:`script/script_file functions on sol::state/sol::state_view<state-script-function>`
Scripts can have syntax errors, can load from the file system wrong, or have runtime issues. Knowing which one can be troublesome. There are various small building blocks to load and run code, but to check errors you can use the overloaded :ref:`script/script_file functions on sol::state/sol::state_view<state-script-function>`, specifically the ``safe_script`` variants. These also take an error callback that is called only when something goes wrong, and Sol comes with some default error handlers in the form of ``sol::script_default_on_error`` and ``sol::script_pass_on_error``.
Compiler Errors / Warnings
--------------------------
@ -20,7 +20,20 @@ A myriad of compiler errors can occur when something goes wrong. Here is some ba
* Template depth errors may also be a problem on earlier versions of clang++ and g++. Use ``-ftemplate-depth`` compiler flag and specify really high number (something like 2048 or even double that amount) to let the compiler work freely. Also consider potentially using :doc:`simple usertypes<api/simple_usertype>` to save compilation speed.
* If you have a move-only type, that type may need to be made ``readonly`` if it is bound as a member variable on a usertype or bound using ``state_view::set_function``. See :doc:`sol::readonly<api/readonly>` for more details.
* Assigning a ``std::string`` or a ``std::pair<T1, T2>`` using ``operator=`` after it's been constructed can result in compiler errors when working with ``sol::function`` and its results. See `this issue for fixes to this behavior`_.
* Sometimes, using ``__stdcall`` in a 32-bit (x86) environment on VC++ can cause problems binding functions because of a compiler bug. Put the function in a ``std::function`` to make the compiler errors and other problems go away. Also see `this __stdcall issue report`_ for more details.
* Sometimes, using ``__stdcall`` in a 32-bit (x86) environment on VC++ can cause problems binding functions because of a compiler bug. We have a prelimanry fix in, but if it doesn't work and there are still problems: put the function in a ``std::function`` to make the compiler errors and other problems go away. Also see `this __stdcall issue report`_ for more details.
"compiler out of heap space"
----------------------------
Typical of Visual Studio, the compiler will complain that it is out of heap space because Visual Studio defaults to using the x86 (32-bit) version of itself (it will still compile x86 or x64 or ARM binaries, just the compiler **itself** is a 32-bit executable). In order to get around heap space requirements, add the following statement in your ``.vcoxproj`` files under the ``<Import .../>`` statement, as instructed by `OrfeasZ in this issue`_::
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
This should use the 64-bit tools by default, and increase your maximum heap space to whatever a 64-bit windows machine can handle. If you do not have more than 4 GB of RAM, or you still encounter issues, you should look into using ``create_simple_usertype`` and adding functions 1 by 1 using ``.set( ... )``, as shown in `the simple usertype example here`_.
Linker Errors
@ -72,3 +85,4 @@ Tables may have other junk on them that makes iterating through their numeric pa
.. _this issue for fixes to this behavior: https://github.com/ThePhD/sol2/issues/414#issuecomment-306839439
.. _this __stdcall issue report: https://github.com/ThePhD/sol2/issues/463
.. _the simple usertype example here: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp#L45

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2017-08-24 18:56:19.661582 UTC
// This header was generated with sol v2.18.0 (revision 92a6fb8)
// Generated 2017-08-27 04:00:40.261712 UTC
// This header was generated with sol v2.18.1 (revision 626da4d)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -9108,6 +9108,11 @@ namespace sol {
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);
@ -9125,7 +9130,7 @@ namespace sol {
int stack_index() const { return index; };
int return_count() const { return returncount; };
void abandon() noexcept {
L = nullptr;
//L = nullptr;
index = 0;
returncount = 0;
}
@ -11505,6 +11510,11 @@ namespace sol {
return *this;
}
protected_function_result(const function_result& o) = delete;
protected_function_result& operator=(const function_result& o) = delete;
protected_function_result(function_result&& o) noexcept;
protected_function_result& operator=(function_result&& o) noexcept;
call_status status() const noexcept {
return err;
}
@ -11523,7 +11533,7 @@ namespace sol {
int return_count() const noexcept { return returncount; };
int pop_count() const noexcept { return popcount; };
void abandon() noexcept {
L = nullptr;
//L = nullptr;
index = 0;
returncount = 0;
popcount = 0;
@ -11825,6 +11835,42 @@ namespace sol {
namespace sol {
protected_function_result::protected_function_result(function_result&& o) noexcept : 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
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
protected_function_result& protected_function_result::operator=(function_result&& o) noexcept {
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
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
function_result::function_result(protected_function_result&& o) noexcept : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
function_result& function_result::operator=(protected_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
namespace stack {
template<typename Signature>
struct getter<std::function<Signature>> {

View File

@ -29,6 +29,42 @@
namespace sol {
protected_function_result::protected_function_result(function_result&& o) noexcept : 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
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
protected_function_result& protected_function_result::operator=(function_result&& o) noexcept {
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
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
function_result::function_result(protected_function_result&& o) noexcept : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
}
function_result& function_result::operator=(protected_function_result&& o) noexcept {
L = o.lua_state();
index = o.stack_index();
returncount = o.return_count();
// Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean
// but we will be thorough
o.abandon();
return *this;
}
namespace stack {
template<typename Signature>
struct getter<std::function<Signature>> {

View File

@ -59,6 +59,11 @@ namespace sol {
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);
@ -76,7 +81,7 @@ namespace sol {
int stack_index() const { return index; };
int return_count() const { return returncount; };
void abandon() noexcept {
L = nullptr;
//L = nullptr;
index = 0;
returncount = 0;
}

View File

@ -97,6 +97,11 @@ namespace sol {
return *this;
}
protected_function_result(const function_result& o) = delete;
protected_function_result& operator=(const function_result& o) = delete;
protected_function_result(function_result&& o) noexcept;
protected_function_result& operator=(function_result&& o) noexcept;
call_status status() const noexcept {
return err;
}
@ -115,7 +120,7 @@ namespace sol {
int return_count() const noexcept { return returncount; };
int pop_count() const noexcept { return popcount; };
void abandon() noexcept {
L = nullptr;
//L = nullptr;
index = 0;
returncount = 0;
popcount = 0;

View File

@ -512,5 +512,38 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
REQUIRE(ar == 21);
clean_files();
}
}
TEST_CASE("state/script return converts", "make sure that script return values are convertable from one to another") {
sol::state lua;
sol::protected_function_result r1 = lua.unsafe_script("return 2");
sol::function_result r2 = lua.safe_script("return 3");
int v1 = r1;
int v2 = r2;
REQUIRE(v1 == 2);
REQUIRE(v2 == 3);
}
TEST_CASE("state/script function returns", "make sure that returned functions are converitble from a result to a function") {
SECTION("from result move constructor") {
sol::state lua;
sol::protected_function pf = lua.safe_script("return function () return 2 end", sol::script_pass_on_error);
REQUIRE(pf.valid());
int v1 = pf();
REQUIRE(v1 == 2);
}
SECTION("from result operator=") {
sol::state lua;
sol::protected_function_result r1 = lua.safe_script("return function () return 1 end", sol::script_pass_on_error);
REQUIRE(r1.valid());
sol::protected_function pf = r1;
int v1 = pf();
REQUIRE(v1 == 1);
}
}