config and safety¶
sol was designed to be correct and fast, and in the pursuit of both uses the regular lua_to{x} functions of Lua rather than the checking versions (lua_check{X}) functions. The API defaults to paranoidly-safe alternatives if you have a #define SOL_ALL_SAFETIES_ON before you include sol, or if you pass the SOL_ALL_SAFETIES_ON define on the build command for your build system. By default, it is off and remains off unless you define this, even in debug mode.
config¶
Note that you can obtain safety with regards to functions you bind by using the protect wrapper around function/variable bindings you set into Lua. Additionally, you can have basic boolean checks when using the API by just converting to a sol::optional<T> when necessary for getting things out of Lua and for function arguments.
Also note that you can have your own states use sol3’s safety panics and similar to protect your code from crashes. See sol::state automatic handlers for more details.
Safety Config¶
SOL_SAFE_USERTYPEtriggers the following change:- If the userdata to a usertype function is nil, will trigger an error instead of letting things go through and letting the system segfault/crash
- Turned on by default with clang++, g++ and VC++ if a basic check for building in debug mode is detected (lack of
_NDEBUGor similar compiler-specific checks)
SOL_SAFE_REFERENCEStriggers the following changes:- Checks the Lua type to ensure it matches what you expect it to be upon using sol::reference derived types, such as
sol::thread,sol::function, etc… - Turned on by default with clang++, g++ and VC++ if a basic check for building in debug mode is detected (lack of
_NDEBUGor similar compiler-specific checks)
- Checks the Lua type to ensure it matches what you expect it to be upon using sol::reference derived types, such as
SOL_SAFE_FUNCTION_CALLStriggers the following changes:sol::stack::calland its variants will, if no templated boolean is specified, check all of the arguments for a function call- All calls from Lua will have their arguments checked
- Turned on by default with clang++, g++ and VC++ if a basic check for building in debug mode is detected (lack of
_NDEBUGor similar compiler-specific checks)
SOL_SAFE_FUNCTIONtriggers the following change:- All uses of
sol::functionandsol::stack_functionwill default tosol::protected_functionandsol::stack_protected_function, respectively, rather thansol::unsafe_functionandsol::stack_unsafe_function - Note this does not apply to
sol::stack_aligned_function: this variant must always be unprotected due to stack positioning requirements, especially in use withsol::stack_count
- Note this does not apply to
- All uses of
- Will make any
sol::state_view::scriptcalls default to their safe variants if there is no supplied environment or error handler function - Not turned on by default under any detectible compiler settings: this MUST be turned on manually
SOL_SAFE_NUMERICStriggers the following changes:- Numbers will also be checked to see if they fit within a
lua_Numberif there is nolua_Integertype available that can fit your signed or unsigned number - You can opt-out of this behavior with
SOL_NO_CHECK_NUMBER_PRECISION - This option is required to differentiate between floats/ints in overloads
- Not turned on by default under any settings: this MUST be turned on manually
- Numbers will also be checked to see if they fit within a
SOL_SAFE_GETTERtriggers the following changes:sol::stack::get(used everywhere) defaults to usingsol::stack::check_getand dereferencing the argument. It usessol::type_panicas the handler if something goes wrong- Affects nearly the entire library for safety (with some blind spots covered by the other definitions)
- Not turned on by default under any settings: this MUST be turned on manually
SOL_ALL_SAFETIES_ONtriggers the following changes:- If
SOL_SAFE_USERTYPE,SOL_SAFE_REFERENCES,SOL_SAFE_FUNCTION,SOL_SAFE_NUMERICS,SOL_SAFE_GETTER, andSOL_SAFE_FUNCTION_CALLSare not defined, they get defined and the effects described above kick in - Not turned on by default under any settings: this MUST be turned on manually
- If
SOL_DEFAULT_PASS_ON_ERRORtriggers the following changes:- The default error handler for
sol::state_view::script_functions issol::script_pass_on_errorrather thansol::script_throw_on_error - Passes errors on through: very dangerous as you can ignore or never be warned about errors if you don’t catch the return value of specific functions
- Not turned on by default: this MUST be turned on manually
- Don’t turn this on unless you have an extremely good reason
- DON’T TURN THIS ON UNLESS YOU HAVE AN EXTREMELY GOOD REASON
- The default error handler for
SOL_NO_CHECK_NUMBER_PRECISIONtriggers the following changes:- If
SOL_SAFE_NUMERICSis defined, turns off number precision and integer precision fitting when pushing numbers into sol2 - Not turned on by default under any settings: this MUST be turned on manually
- If
SOL_FUNCTION_CALL_VALUE_SEMANTICStriggers the following changes:- Function arguments and returns into Lua (
sol:functionand similar) do not pass their arguments by reference: they get copied - Individual types can be blessed by template specializing
sol::is_value_semantic_for_function<T> - Not turned on by default under any settings: this MUST be turned on manually
- Function arguments and returns into Lua (
SOL_STRINGS_ARE_NUMBERStriggers the following changes:- Allows automatic to-string conversions for numbers
lua_tolstringconversions are not permitted on numbers through sol3 by default: only actual strings are allowed- This is necessary to allow sol::overload to work properly
sol::stack::getandsol::stack::check_getwill allow anything that Lua thinks is number-worthy to be number-worthy- This includes: integers, floating-point numbers, and strings
- This does not include: booleans, types with
__tostringenabled, and everything else - Overrides safety and always applies if it is turned on
- Not turned on by default under any settings: this MUST be turned on manually
SOL_CHECK_ARGUMENTSis a deprecated define that will be removed soon:- It is simply an alias for
SOL_ALL_SAFETIES_ON - Please change all your code to use
SOL_ALL_SAFETIES_ON
- It is simply an alias for
Feature Config¶
SOL_USE_BOOSTtriggers the following change:- Attempts to use
boost::optionalinstead of sol’s ownoptional - Not turned on by default under any settings: this MUST be turned on manually
- Attempts to use
SOL_PRINT_ERRORStriggers the following change:- Includes
<iostream>and prints all exceptions and errors tostd::cerr, for you to see - Not turned on by default under any settings: this MUST be turned on manually
- Includes
SOL_GET_FUNCTION_POINTERS_UNSAFEtriggers the following change:- Allows function pointers serialized into Lua as a callable to be retrieved back from Lua in a semi-proper manner
- This is under NO circumstances type safe
- It WILL break
sol::overloadtype checking and will not discriminate properly between function types - It WILL happily let you retrieve an
int(*)(int, int int)from avoid(*)()function pointer, and shatter your runtime if you call it
- It WILL break
- This is an advanced, experimental feature for experts only and requires the user has perfect type safety in both C++ and Lua
- Not turned on by default under any settings: this MUST be turned on manually
SOL_CONTAINERS_STARTtriggers the following change:- If defined and is an integral value, is used to adjust the container start value
- Applies to C++ containers only (not Lua tables or algorithms)
- Defaults to 1 (containers in Lua count from 1)
SOL_USE_INTEROPtriggers the following change:- Allows the use of
extensible<T>to be used withuserdata_checkeranduserdata_getterto retrieve non-sol usertypes - Particularly enables non-sol usertypes to be used in overloads
- See the stack documentation for details
- Allows the use of
- May come with a slight performance penalty: only recommended for those stuck with non-sol libraries that still need to leverage some of sol’s power
- Not turned on by default under any settings: this MUST be turned on manually
SOL_DEFAULT_AUTOMAGICAL_USERTYPEStriggers the following change:- Either turns on (
!= 0) or turns off (== 0) automagical usertype detection by default. - Automagical usertypes search for specific C++ conventions to define common methods for the end-user.
- Some automagical methods might cause huge compiler errors, and some people have code bases with different conventions.
- Turned on by default. This must be turned off manually.
- Either turns on (
SOL_NO_THREAD_LOCALtriggers the following change:- If this is turned on, simply removes all usages of the
thread_localkeyword in sol2. - This is useful for lower versions of iOS and Android, which do not have threading capabilities at all and so the use of the keyword provides no additional guarantees.
- Not turned on by default under any settings: this MUST be turned on manually
- If this is turned on, simply removes all usages of the
SOL_ID_SIZEtriggers the following change:- If this is defined to a numeric value, it uses that numeric value for the number of bytes of input to be put into the error message blurb in standard tracebacks and
chunknamedescriptions for.script/.script_fileusage. - Defaults to the
LUA_ID_SIZEmacro if defined, or some basic internal value like 2048.
- If this is defined to a numeric value, it uses that numeric value for the number of bytes of input to be put into the error message blurb in standard tracebacks and
SOL_LUAJITtriggers the following change:- Has sol2 expect LuaJIT, and all of its quirks.
- Turns on by default if the macro
LUAJIT_VERSIONis detected from including Lua headers without any work on your part. Can also be manually defined.
Memory Config¶
SOL_NO_MEMORY_ALIGNMENTtriggers the following changes:- Memory is no longer aligned and is instead directly sized and allocated
- If you need to access underlying userdata memory from sol, please see the usertype memory documentation
- Not turned on by default under any settings: this MUST be turned on manually
Linker Config¶
SOL_USING_CXX_LUAtriggers the following changes:- Lua includes are no longer wrapped in
extern "C" {}blocks SOL_NO_LUA_HPPtakes less precedence if this is explicitly turned on- Turns on
SOL_EXCEPTIONS_SAFE_PROPAGATIONautomatically for you - Only use this if you know you’ve built your LuaJIT with the C++-specific invocations of your compiler (Lua by default builds as C code and is not distributed as a C++ library, but a C one with C symbols)
- Lua includes are no longer wrapped in
SOL_USING_CXX_LUA_JITtriggers the following changes:- LuaJIT includes are no longer wrapped in
extern "C" {}blocks - Turns on
SOL_EXCEPTIONS_SAFE_PROPAGATIONautomatically for you - Only use this if you know you’ve built your LuaJIT with the C++-specific invocations of your compiler
- LuaJIT by default builds as C code, but includes hook to handle C++ code unwinding: this should almost never be necessary for regular builds
- LuaJIT includes are no longer wrapped in
SOL_EXCEPTIONS_ALWAYS_UNSAFEtriggers the following changes:- If any of the
SOL_USING_CXX_*defines are in play, it does NOT automatically turn onSOL_EXCEPTIONS_SAFE_PROPAGATIONautomatically - This standardizes some behavior, since throwing exceptions through the C API’s interface can still lead to undefined behavior that Lua cannot handle properly
- If any of the
SOL_EXCEPTIONS_SAFE_PROPAGATIONtriggers the following changes:- try/catch will not be used around C-function trampolines when going from Lua to C++
- try/catch will not be used in
safe_/protected_functioninternals - Should only be used in accordance with compiling vanilla PUC-RIO Lua as C++, using LuaJIT under the proper conditions, or in accordance with your Lua distribution’s documentation
Tests are compiled with this on to ensure everything is going as expected. Remember that if you want these features, you must explicitly turn them on all of them to be sure you are getting them.
memory¶
Memory safety can be tricky. Lua is handled by a garbage-collected runtime, meaning object deletion is not cleary defined or deterministic. If you need to keep an object from the Lua Runtime alive, use sol::reference or one of its derived types, such as sol::table, sol::object, or similar. These will pin a reference down to an object controlled in C++, and Lua will not delete an object that you still have a reference to through one of these types. You can then retrieve whatever you need from that Lua slot using object’s obj.as<T>() member function or other things, and work on the memory from there.
The usertype memory layout for all Lua-instantiated userdata and for all objects pushed/set into the Lua Runtime is also described here. Things before or after that specified memory slot is implementation-defined and no assumptions are to be made about it.
Please be wary of alignment issues. sol3 aligns memory by default. If you need to access underlying userdata memory from sol, please see the usertype memory documentation
functions¶
The vast majority of all users are going to want to work with sol::safe_function/sol::protected_function. This version allows for error checking, prunes results, and responds to the defines listed above by throwing errors if you try to use the result of a function without checking. sol::function/sol::unsafe_function is unsafe. It assumes that its contents run correctly and throw no errors, which can result in crashes that are hard to debug while offering a very tiny performance boost for not checking error codes or catching exceptions.
If you find yourself crashing inside of sol::function, try changing it to a sol::protected_function and seeing if the error codes and such help you find out what’s going on. You can read more about the API on the page itself. You can also define SOL_SAFE_FUNCTION as described above, but be warned that the protected_function API is a superset of the regular default function API: trying to revert back after defining SOL_SAFE_FUNCTION may result in some compiler errors if you use things beyond the basic, shared interface of the two types.
As a side note, binding functions with default parameters does not magically bind multiple versions of the function to be called with the default parameters. You must instead use sol::overload.
Warning
Do NOT save the return type of a 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 here for more information.