mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
add single, add examples
This commit is contained in:
parent
c3c7f42d91
commit
e06d2fb581
|
@ -61,7 +61,7 @@ if (EXAMPLES)
|
|||
source_group(examples FILES ${EXAMPLES_SRC})
|
||||
foreach(example_source_file ${EXAMPLES_SRC})
|
||||
get_filename_component(example_name ${example_source_file} NAME_WE)
|
||||
set(example_name "example-${example_name}")
|
||||
set(example_name "example_${example_name}")
|
||||
add_executable(${example_name} ${example_source_file} ${HEADER_SRCS})
|
||||
target_link_libraries(${example_name} ${LUA_LIBRARIES})
|
||||
target_compile_features(${example_name} PUBLIC ${CXX_FEATURES})
|
||||
|
@ -74,7 +74,7 @@ if (TESTS)
|
|||
source_group(tests FILES ${TEST_SRC})
|
||||
|
||||
add_executable(tests ${TEST_SRC} ${HEADER_SRCS})
|
||||
target_include_directories(tests PRIVATE ./Catch/include/)
|
||||
target_include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR}/Catch/include/)
|
||||
|
||||
find_package(Threads)
|
||||
target_link_libraries(tests Threads::Threads ${LUA_LIBRARIES})
|
||||
|
@ -83,10 +83,10 @@ endif()
|
|||
|
||||
find_package(PythonInterp 3)
|
||||
if (PYTHONINTERP_FOUND)
|
||||
add_custom_command(OUTPUT single/sol/sol.hpp single/sol/sol_forward.hpp COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/single.py --output ${CMAKE_CURRENT_SOURCE_DIR}/single/sol/sol.hpp DEPENDS ${HEADER_SRCS})
|
||||
add_custom_command(OUTPUT single/sol/sol.hpp single/sol/sol_forward.hpp COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/single.py --output ${CMAKE_CURRENT_BINARY_DIR}/single/sol/sol.hpp DEPENDS ${HEADER_SRCS})
|
||||
add_custom_target(single_sol DEPENDS single/sol/sol.hpp single/sol/sol_forward.hpp)
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/single/sol/sol.hpp" DESTINATION include/sol)
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/single/sol/sol_forward.hpp" DESTINATION include/sol)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/single/sol/sol.hpp" DESTINATION include/sol)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/single/sol/sol_forward.hpp" DESTINATION include/sol)
|
||||
message(STATUS "single_sol can be generated as python 3 has been found.")
|
||||
else()
|
||||
message(STATUS "single_sol cannot be generated as python 3 has not been found.")
|
||||
|
|
|
@ -88,6 +88,32 @@ You may also retrieve an :doc:`sol::optional\<T><optional>` from this as well, t
|
|||
|
||||
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. If you do not pass your own handler, a ``no_panic`` handler will be passed.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: get_usertype
|
||||
:name: stack-get-usertype
|
||||
|
||||
template <typename T>
|
||||
auto get_usertype( lua_State* L, int index = -1 )
|
||||
template <typename T>
|
||||
auto get_usertype( lua_State* L, int index, record& tracking )
|
||||
|
||||
Directly attempts to rertieve the type ``T`` using sol2's usertype mechanisms. Similar to a regular ``get`` for a user-defined type. Useful when you need to access sol2's usertype getter mechanism while at the same time `providing your own customization`_.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: check_usertype
|
||||
:name: stack-check
|
||||
|
||||
template <typename T>
|
||||
bool check_usertype( lua_State* L, int index = -1 )
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype( lua_State* L, int index, Handler&& handler )
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype( lua_State* L, int index, Handler&& handler, record& tracking )
|
||||
|
||||
Checks if the object at ``index`` is of type ``T`` and stored as a sol2 usertype. Useful when you need to access sol2's usertype checker mechanism while at the same time `providing your own customization`_.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: check_get
|
||||
:name: stack-check-get
|
||||
|
@ -305,3 +331,4 @@ This is an SFINAE-friendly struct that is meant to expose a function ``get`` tha
|
|||
.. _Lua stack works in general: https://www.lua.org/pil/24.2.html
|
||||
.. _calling C functions works: https://www.lua.org/pil/26.html
|
||||
.. _interop examples: https://github.com/ThePhD/sol2/blob/develop/examples/interop
|
||||
.. _providing your own customization: https://github.com/ThePhD/sol2/blob/develop/examples/customization_convert_on_get.cpp
|
||||
|
|
|
@ -238,6 +238,8 @@ If you don't specify a ``sol::meta_function`` name (or equivalent string metamet
|
|||
- a ``sol::meta_function::pairs`` operator is generated for you
|
||||
- Allows you to iterate using ``for k, v in pairs( obj ) do ... end`` in Lua
|
||||
- **Lua 5.2 and better only: LuaJIT does not allow this, Lua 5.1 does NOT allow this**
|
||||
* for cases where ``.size()`` exists on the C++ type
|
||||
- the length operator of Lua (``#my_obj``) operator is generated for you
|
||||
* for comparison operations where ``operator <`` and ``operator <=`` exist on the C++ type
|
||||
- These two ``sol::meta_function::less_than(_or_equal_to)`` are generated for you
|
||||
- ``>`` and ``>=`` operators are generated in Lua based on ``<`` and ``<=`` operators
|
||||
|
@ -264,8 +266,9 @@ Otherwise, the following is used to specify functions to bind on the specific us
|
|||
- Binds a typical variable to ``"{name}"``, but gets and sets using the specified setter and getter functions. Not that if you do not pass a setter function, the variable will be read-only. Also not that if you do not pass a getter function, it will be write-only
|
||||
* ``"{name}", sol::var( some_value )`` or ``"{name}", sol::var( std::ref( some_value ) )``
|
||||
- Binds a typical variable to ``"{name}"``, optionally by reference (e.g., refers to the same memory in C++). This is useful for global variables / static class variables and the like
|
||||
* ``"{name}", sol::overloaded( Func1, Func2, ... )``
|
||||
- Creates an oveloaded member function that discriminates on number of arguments and types.
|
||||
* ``"{name}", sol::overload( Func1, Func2, ... )``
|
||||
- Creates an oveloaded member function that discriminates on number of arguments and types
|
||||
- Dumping multiple functions out with the same name **does not make an overload**: you must use **this syntax** in order for it to work
|
||||
* ``sol::base_classes, sol::bases<Bases...>``
|
||||
- Tells a usertype what its base classes are. You need this to have derived-to-base conversions work properly. See :ref:`inheritance<usertype-inheritance>`
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
struct two_things {
|
||||
|
|
68
examples/customization_convert_on_get.cpp
Normal file
68
examples/customization_convert_on_get.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
struct number_shim {
|
||||
double num = 0;
|
||||
};
|
||||
|
||||
namespace sol {
|
||||
|
||||
template <>
|
||||
struct lua_type_of<number_shim> : std::integral_constant<sol::type, sol::type::poly> {};
|
||||
|
||||
namespace stack {
|
||||
template <>
|
||||
struct checker<number_shim> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
// check_usertype is a backdoor for directly checking sol2 usertypes
|
||||
if (!check_usertype<number_shim>(L, index) && !stack::check<double>(L, index)) {
|
||||
handler(L, index, type_of(L, index), type::userdata, "expected a number_shim or a number");
|
||||
return false;
|
||||
}
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<number_shim> {
|
||||
static number_shim get(lua_State* L, int index, record& tracking) {
|
||||
if (check_usertype<number_shim>(L, index)) {
|
||||
number_shim& ns = get_usertype<number_shim>(L, index, tracking);
|
||||
return ns;
|
||||
}
|
||||
number_shim ns{};
|
||||
ns.num = stack::get<double>(L, index, tracking);
|
||||
return ns;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace stack
|
||||
} // namespace sol
|
||||
|
||||
int main() {
|
||||
sol::state lua;
|
||||
|
||||
// Create a pass-through style of function
|
||||
lua.safe_script("function f ( a ) return a end");
|
||||
lua.set_function("g", [](double a) {
|
||||
number_shim ns;
|
||||
ns.num = a;
|
||||
return ns;
|
||||
});
|
||||
|
||||
lua.script("vf = f(25) vg = g(35)");
|
||||
|
||||
number_shim thingsf = lua["vf"];
|
||||
number_shim thingsg = lua["vg"];
|
||||
|
||||
assert(thingsf.num == 25);
|
||||
assert(thingsg.num == 35);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -191,7 +191,11 @@ if not args.quiet:
|
|||
print('finished creating single forward declaration header for sol\n')
|
||||
|
||||
with open(single_file, 'w', encoding='utf-8') as f:
|
||||
if not args.quiet:
|
||||
print('writing {}...'.format(single_file))
|
||||
f.write(result)
|
||||
|
||||
with open(forward_single_file, 'w', encoding='utf-8') as f:
|
||||
if not args.quiet:
|
||||
print('writing {}...'.format(single_file))
|
||||
f.write(forward_result)
|
||||
|
|
|
@ -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-12-10 06:34:23.982786 UTC
|
||||
// This header was generated with sol v2.19.0 (revision 87b4dd6)
|
||||
// Generated 2017-12-10 20:56:35.224200 UTC
|
||||
// This header was generated with sol v2.19.0 (revision c3c7f42)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -72,7 +72,6 @@
|
|||
|
||||
#if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)))
|
||||
#ifndef SOL_NOEXCEPT_FUNCTION_TYPE
|
||||
#define SOL_NOEXCEPT_FUNCTION_TYPE 1
|
||||
#endif // noexcept is part of a function's type
|
||||
#endif
|
||||
|
||||
|
@ -4439,6 +4438,11 @@ namespace sol {
|
|||
int static_trampoline_noexcept(lua_State* L) noexcept {
|
||||
return f(L);
|
||||
}
|
||||
#else
|
||||
template <lua_CFunction f>
|
||||
int static_trampoline_noexcept(lua_State* L) noexcept {
|
||||
return f(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
|
@ -7099,6 +7103,20 @@ namespace sol {
|
|||
use_reference_tag;
|
||||
return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(std::false_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<T> Tu;
|
||||
typedef detail::as_value_tag<Tu> detail_t;
|
||||
return checker<detail_t, type::userdata>{}.check(types<meta::unqualified_t<T>>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(std::true_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<std::remove_pointer_t<meta::unqualified_t<T>>> Tu;
|
||||
typedef detail::as_pointer_tag<Tu> detail_t;
|
||||
return checker<detail_t, type::userdata>{}.check(L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
} // namespace stack_detail
|
||||
|
||||
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
||||
|
@ -7198,6 +7216,24 @@ namespace sol {
|
|||
return check<T>(L, index, handler);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
type indextype = type_of(L, index);
|
||||
return stack_detail::check_usertype<T>(std::is_pointer<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(lua_State* L, int index, Handler&& handler) {
|
||||
record tracking{};
|
||||
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||
auto handler = no_panic;
|
||||
return check_usertype<T>(L, index, handler);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<T> Tu;
|
||||
|
@ -7226,6 +7262,11 @@ namespace sol {
|
|||
auto op = check_get<T>(L, index, type_panic_c_str, tracking);
|
||||
return *std::move(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<T>, lua_State* L, int index, record& tracking) {
|
||||
|
@ -7233,11 +7274,6 @@ namespace sol {
|
|||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
||||
}
|
||||
|
||||
template <bool b>
|
||||
struct check_types {
|
||||
template <typename T, typename... Args, typename Handler>
|
||||
|
@ -7295,6 +7331,21 @@ namespace sol {
|
|||
return multi_check<true, Args...>(L, index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
|
||||
#ifdef SOL_SAFE_GETTER
|
||||
return stack_detail::tagged_get(types<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(), L, index, tracking);
|
||||
#else
|
||||
return stack_detail::unchecked_get<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(L, index, tracking);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||
record tracking{};
|
||||
return get_usertype<T>(L, index, tracking);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::tagged_get(types<T>(), L, index, tracking);
|
||||
|
@ -7578,17 +7629,21 @@ namespace stack {
|
|||
int isnum = 0;
|
||||
lua_tointegerx(L, index, &isnum);
|
||||
const bool success = isnum != 0;
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string");
|
||||
}
|
||||
#else
|
||||
// this check is precise, does not convert
|
||||
if (lua_isinteger(L, index) == 1) {
|
||||
return true;
|
||||
}
|
||||
const bool success = false;
|
||||
#endif // If numbers are enabled, use the imprecise check
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::number, type_of(L, index), "not a numeric type");
|
||||
}
|
||||
#endif // If numbers are enabled, use the imprecise check
|
||||
return success;
|
||||
#else
|
||||
#ifndef SOL_STRINGS_ARE_NUMBERS
|
||||
|
@ -7887,6 +7942,12 @@ namespace stack {
|
|||
|
||||
template <typename T, typename C>
|
||||
struct checker<detail::as_value_tag<T>, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
return check(types<T>(), L, index, indextype, handler, tracking);
|
||||
}
|
||||
|
||||
template <typename U, typename Handler>
|
||||
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
#ifdef SOL_ENABLE_INTEROP
|
||||
|
@ -7937,11 +7998,28 @@ namespace stack {
|
|||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
struct checker<detail::as_pointer_tag<T>, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
if (indextype == type::lua_nil) {
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
return stack_detail::check_usertype<T>(std::false_type(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
return check(L, index, handler, indextype, tracking);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7949,13 +8027,7 @@ namespace stack {
|
|||
struct checker<T*, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
// Allow lua_nil to be transformed to nullptr
|
||||
if (indextype == type::lua_nil) {
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking);
|
||||
return check_usertype<T*>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15148,9 +15220,8 @@ namespace sol {
|
|||
};
|
||||
|
||||
static auto& get_src(lua_State* L) {
|
||||
typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> Tu;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
auto p = stack::check_get<Tu*>(L, 1);
|
||||
auto p = stack::check_get<T*>(L, 1);
|
||||
if (!p) {
|
||||
luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str());
|
||||
}
|
||||
|
@ -17050,14 +17121,21 @@ namespace sol {
|
|||
if (toplevel && stack::get<type>(L, keyidx) != type::string) {
|
||||
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
|
||||
}
|
||||
int runtime_target = 0;
|
||||
usertype_detail::member_search member = nullptr;
|
||||
{
|
||||
std::string name = stack::get<std::string>(L, keyidx);
|
||||
auto memberit = f.mapping.find(name);
|
||||
if (memberit != f.mapping.cend()) {
|
||||
const usertype_detail::call_information& ci = memberit->second;
|
||||
const usertype_detail::member_search& member = is_index ? ci.index : ci.new_index;
|
||||
return (member)(L, static_cast<void*>(&f), ci.runtime_target);
|
||||
member = is_index ? ci.index : ci.new_index;
|
||||
runtime_target = ci.runtime_target;
|
||||
}
|
||||
string_view accessor = name;
|
||||
}
|
||||
if (member != nullptr) {
|
||||
return (member)(L, static_cast<void*>(&f), runtime_target);
|
||||
}
|
||||
string_view accessor = stack::get<string_view>(L, keyidx);
|
||||
int ret = 0;
|
||||
bool found = false;
|
||||
// Otherwise, we need to do propagating calls through the bases
|
||||
|
@ -17311,7 +17389,7 @@ namespace sol {
|
|||
function_map& functions = sm.functions;
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel) {
|
||||
if (stack::get<type>(L, keyidx) != type::string) {
|
||||
if (type_of(L, keyidx) != type::string) {
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
|
@ -17326,15 +17404,20 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
string_view accessor = stack::get<string_view>(L, keyidx);
|
||||
std::string accessorkey = accessor.data();
|
||||
variable_wrapper* varwrap = nullptr;
|
||||
{
|
||||
std::string accessorkey(accessor.data(), accessor.size());
|
||||
auto vit = variables.find(accessorkey);
|
||||
if (vit != variables.cend()) {
|
||||
auto& varwrap = *(vit->second);
|
||||
if (is_index) {
|
||||
return varwrap.index(L);
|
||||
varwrap = vit->second.get();
|
||||
}
|
||||
return varwrap.new_index(L);
|
||||
}
|
||||
if (varwrap != nullptr) {
|
||||
return is_index ? varwrap->index(L) : varwrap->new_index(L);
|
||||
}
|
||||
bool function_failed = false;
|
||||
{
|
||||
std::string accessorkey(accessor.data(), accessor.size());
|
||||
auto fit = functions.find(accessorkey);
|
||||
if (fit != functions.cend()) {
|
||||
object& func = fit->second;
|
||||
|
@ -17342,6 +17425,11 @@ namespace sol {
|
|||
return stack::push(L, func);
|
||||
}
|
||||
else {
|
||||
function_failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (function_failed) {
|
||||
if (has_indexing && !is_toplevel(L)) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
|
@ -17354,7 +17442,6 @@ namespace sol {
|
|||
: metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check table storage first for a method that works
|
||||
luaL_getmetatable(L, sm.metakey);
|
||||
if (type_of(L, -1) != type::lua_nil) {
|
||||
|
|
|
@ -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-12-10 06:34:24.172779 UTC
|
||||
// This header was generated with sol v2.19.0 (revision 87b4dd6)
|
||||
// Generated 2017-12-10 20:56:35.410742 UTC
|
||||
// This header was generated with sol v2.19.0 (revision c3c7f42)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||
|
@ -39,7 +39,6 @@
|
|||
|
||||
#if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)))
|
||||
#ifndef SOL_NOEXCEPT_FUNCTION_TYPE
|
||||
#define SOL_NOEXCEPT_FUNCTION_TYPE 1
|
||||
#endif // noexcept is part of a function's type
|
||||
#endif
|
||||
|
||||
|
|
|
@ -538,9 +538,8 @@ namespace sol {
|
|||
};
|
||||
|
||||
static auto& get_src(lua_State* L) {
|
||||
typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> Tu;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
auto p = stack::check_get<Tu*>(L, 1);
|
||||
auto p = stack::check_get<T*>(L, 1);
|
||||
if (!p) {
|
||||
luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str());
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)))
|
||||
#ifndef SOL_NOEXCEPT_FUNCTION_TYPE
|
||||
#define SOL_NOEXCEPT_FUNCTION_TYPE 1
|
||||
//#define SOL_NOEXCEPT_FUNCTION_TYPE 1
|
||||
#endif // noexcept is part of a function's type
|
||||
#endif
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace sol {
|
|||
function_map& functions = sm.functions;
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel) {
|
||||
if (stack::get<type>(L, keyidx) != type::string) {
|
||||
if (type_of(L, keyidx) != type::string) {
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
|
@ -66,15 +66,20 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
string_view accessor = stack::get<string_view>(L, keyidx);
|
||||
std::string accessorkey = accessor.data();
|
||||
variable_wrapper* varwrap = nullptr;
|
||||
{
|
||||
std::string accessorkey(accessor.data(), accessor.size());
|
||||
auto vit = variables.find(accessorkey);
|
||||
if (vit != variables.cend()) {
|
||||
auto& varwrap = *(vit->second);
|
||||
if (is_index) {
|
||||
return varwrap.index(L);
|
||||
varwrap = vit->second.get();
|
||||
}
|
||||
return varwrap.new_index(L);
|
||||
}
|
||||
if (varwrap != nullptr) {
|
||||
return is_index ? varwrap->index(L) : varwrap->new_index(L);
|
||||
}
|
||||
bool function_failed = false;
|
||||
{
|
||||
std::string accessorkey(accessor.data(), accessor.size());
|
||||
auto fit = functions.find(accessorkey);
|
||||
if (fit != functions.cend()) {
|
||||
object& func = fit->second;
|
||||
|
@ -82,6 +87,11 @@ namespace sol {
|
|||
return stack::push(L, func);
|
||||
}
|
||||
else {
|
||||
function_failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (function_failed) {
|
||||
if (has_indexing && !is_toplevel(L)) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
|
@ -94,7 +104,6 @@ namespace sol {
|
|||
: metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check table storage first for a method that works
|
||||
luaL_getmetatable(L, sm.metakey);
|
||||
if (type_of(L, -1) != type::lua_nil) {
|
||||
|
|
|
@ -99,17 +99,21 @@ namespace stack {
|
|||
int isnum = 0;
|
||||
lua_tointegerx(L, index, &isnum);
|
||||
const bool success = isnum != 0;
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string");
|
||||
}
|
||||
#else
|
||||
// this check is precise, does not convert
|
||||
if (lua_isinteger(L, index) == 1) {
|
||||
return true;
|
||||
}
|
||||
const bool success = false;
|
||||
#endif // If numbers are enabled, use the imprecise check
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(L, index, type::number, type_of(L, index), "not a numeric type");
|
||||
}
|
||||
#endif // If numbers are enabled, use the imprecise check
|
||||
return success;
|
||||
#else
|
||||
#ifndef SOL_STRINGS_ARE_NUMBERS
|
||||
|
@ -408,6 +412,12 @@ namespace stack {
|
|||
|
||||
template <typename T, typename C>
|
||||
struct checker<detail::as_value_tag<T>, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
return check(types<T>(), L, index, indextype, handler, tracking);
|
||||
}
|
||||
|
||||
template <typename U, typename Handler>
|
||||
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
#ifdef SOL_ENABLE_INTEROP
|
||||
|
@ -458,11 +468,28 @@ namespace stack {
|
|||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
struct checker<detail::as_pointer_tag<T>, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
if (indextype == type::lua_nil) {
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
return stack_detail::check_usertype<T>(std::false_type(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
return check(L, index, handler, indextype, tracking);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -470,13 +497,7 @@ namespace stack {
|
|||
struct checker<T*, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
const type indextype = type_of(L, index);
|
||||
// Allow lua_nil to be transformed to nullptr
|
||||
if (indextype == type::lua_nil) {
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking);
|
||||
return check_usertype<T*>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -550,6 +550,20 @@ namespace sol {
|
|||
use_reference_tag;
|
||||
return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(std::false_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<T> Tu;
|
||||
typedef detail::as_value_tag<Tu> detail_t;
|
||||
return checker<detail_t, type::userdata>{}.check(types<meta::unqualified_t<T>>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(std::true_type, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<std::remove_pointer_t<meta::unqualified_t<T>>> Tu;
|
||||
typedef detail::as_pointer_tag<Tu> detail_t;
|
||||
return checker<detail_t, type::userdata>{}.check(L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
} // namespace stack_detail
|
||||
|
||||
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
||||
|
@ -649,6 +663,24 @@ namespace sol {
|
|||
return check<T>(L, index, handler);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
type indextype = type_of(L, index);
|
||||
return stack_detail::check_usertype<T>(std::is_pointer<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check_usertype(lua_State* L, int index, Handler&& handler) {
|
||||
record tracking{};
|
||||
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||
auto handler = no_panic;
|
||||
return check_usertype<T>(L, index, handler);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
typedef meta::unqualified_t<T> Tu;
|
||||
|
@ -677,6 +709,11 @@ namespace sol {
|
|||
auto op = check_get<T>(L, index, type_panic_c_str, tracking);
|
||||
return *std::move(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<T>, lua_State* L, int index, record& tracking) {
|
||||
|
@ -684,11 +721,6 @@ namespace sol {
|
|||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
||||
}
|
||||
|
||||
template <bool b>
|
||||
struct check_types {
|
||||
template <typename T, typename... Args, typename Handler>
|
||||
|
@ -746,6 +778,21 @@ namespace sol {
|
|||
return multi_check<true, Args...>(L, index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
|
||||
#ifdef SOL_SAFE_GETTER
|
||||
return stack_detail::tagged_get(types<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(), L, index, tracking);
|
||||
#else
|
||||
return stack_detail::unchecked_get<std::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>>(L, index, tracking);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||
record tracking{};
|
||||
return get_usertype<T>(L, index, tracking);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||
return stack_detail::tagged_get(types<T>(), L, index, tracking);
|
||||
|
|
|
@ -57,6 +57,11 @@ namespace sol {
|
|||
int static_trampoline_noexcept(lua_State* L) noexcept {
|
||||
return f(L);
|
||||
}
|
||||
#else
|
||||
template <lua_CFunction f>
|
||||
int static_trampoline_noexcept(lua_State* L) noexcept {
|
||||
return f(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
|
|
|
@ -555,14 +555,21 @@ namespace sol {
|
|||
if (toplevel && stack::get<type>(L, keyidx) != type::string) {
|
||||
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
|
||||
}
|
||||
int runtime_target = 0;
|
||||
usertype_detail::member_search member = nullptr;
|
||||
{
|
||||
std::string name = stack::get<std::string>(L, keyidx);
|
||||
auto memberit = f.mapping.find(name);
|
||||
if (memberit != f.mapping.cend()) {
|
||||
const usertype_detail::call_information& ci = memberit->second;
|
||||
const usertype_detail::member_search& member = is_index ? ci.index : ci.new_index;
|
||||
return (member)(L, static_cast<void*>(&f), ci.runtime_target);
|
||||
member = is_index ? ci.index : ci.new_index;
|
||||
runtime_target = ci.runtime_target;
|
||||
}
|
||||
string_view accessor = name;
|
||||
}
|
||||
if (member != nullptr) {
|
||||
return (member)(L, static_cast<void*>(&f), runtime_target);
|
||||
}
|
||||
string_view accessor = stack::get<string_view>(L, keyidx);
|
||||
int ret = 0;
|
||||
bool found = false;
|
||||
// Otherwise, we need to do propagating calls through the bases
|
||||
|
|
|
@ -772,9 +772,7 @@ y = a.readonly_seq
|
|||
std::list<bar>& seqrefy = lua["y"];
|
||||
REQUIRE(&seqrefx == &seqrefy);
|
||||
REQUIRE(seqrefx.size() == 3);
|
||||
auto result = lua.do_string(R"(
|
||||
a.readonly_seq = value;
|
||||
)");
|
||||
auto result = lua.safe_script("a.readonly_seq = value", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(result.valid());
|
||||
}
|
||||
|
||||
|
@ -903,7 +901,7 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
|
|||
|
||||
lua["v"] = std::vector<non_copyable>{};
|
||||
|
||||
auto pfr = lua.safe_script("t = test.new()\nt.b = v", sol::script_pass_on_error);
|
||||
auto pfr = lua.safe_script("t = test.new() t.b = v", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(pfr.valid());
|
||||
}
|
||||
SECTION("simple") {
|
||||
|
@ -913,7 +911,7 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
|
|||
|
||||
lua["v"] = std::vector<non_copyable>{};
|
||||
|
||||
auto pfr = lua.safe_script("t = test.new()\nt.b = v", sol::script_pass_on_error);
|
||||
auto pfr = lua.safe_script("t = test.new() t.b = v", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(pfr.valid());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ struct two_things {
|
|||
bool b;
|
||||
};
|
||||
|
||||
struct number_shim {
|
||||
double num = 0;
|
||||
};
|
||||
|
||||
namespace sol {
|
||||
|
||||
// First, the expected size
|
||||
|
@ -23,6 +27,10 @@ namespace sol {
|
|||
template <>
|
||||
struct lua_type_of<two_things> : std::integral_constant<sol::type, sol::type::poly> {};
|
||||
|
||||
// do note specialize size for this because it is our type
|
||||
template <>
|
||||
struct lua_type_of<number_shim> : std::integral_constant<sol::type, sol::type::poly> {};
|
||||
|
||||
// Now, specialize various stack structures
|
||||
namespace stack {
|
||||
|
||||
|
@ -62,6 +70,33 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct checker<number_shim> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
// check_usertype is a backdoor for directly checking sol2 usertypes
|
||||
if (!check_usertype<number_shim>(L, index) && !stack::check<double>(L, index)) {
|
||||
handler(L, index, type_of(L, index), type::userdata, "expected a number_shim or a number");
|
||||
return false;
|
||||
}
|
||||
tracking.use(1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<number_shim> {
|
||||
static number_shim get(lua_State* L, int index, record& tracking) {
|
||||
if (check_usertype<number_shim>(L, index)) {
|
||||
number_shim& ns = get_usertype<number_shim>(L, index, tracking);
|
||||
return ns;
|
||||
}
|
||||
number_shim ns{};
|
||||
ns.num = stack::get<double>(L, index, tracking);
|
||||
return ns;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace stack
|
||||
} // namespace sol
|
||||
|
||||
|
@ -89,3 +124,24 @@ TEST_CASE("customization/split struct", "using the newly documented customizatio
|
|||
REQUIRE_FALSE(thingsg.b);
|
||||
REQUIRE(d == 36.5);
|
||||
}
|
||||
|
||||
TEST_CASE("customization/get_ check_usertype", "using the newly documented customization points to handle different kinds of classes") {
|
||||
sol::state lua;
|
||||
|
||||
// Create a pass-through style of function
|
||||
lua.safe_script("function f ( a ) return a end");
|
||||
lua.set_function("g", [](double a) {
|
||||
number_shim ns;
|
||||
ns.num = a;
|
||||
return ns;
|
||||
});
|
||||
|
||||
auto result = lua.safe_script("vf = f(25) vg = g(35)", sol::script_pass_on_error);
|
||||
REQUIRE(result.valid());
|
||||
|
||||
number_shim thingsf = lua["vf"];
|
||||
number_shim thingsg = lua["vg"];
|
||||
|
||||
REQUIRE(thingsf.num == 25);
|
||||
REQUIRE(thingsg.num == 35);
|
||||
}
|
||||
|
|
|
@ -635,15 +635,14 @@ end
|
|||
REQUIRE_FALSE(result.valid());
|
||||
}
|
||||
|
||||
REQUIRE_NOTHROW([&lua]() {
|
||||
{
|
||||
auto result = lua.safe_script(R"(
|
||||
function t:runtime_func(a)
|
||||
return a + 52
|
||||
end
|
||||
)",
|
||||
sol::script_pass_on_error);
|
||||
)", sol::script_pass_on_error);
|
||||
REQUIRE_FALSE(result.valid());
|
||||
}());
|
||||
}
|
||||
|
||||
lua.safe_script("val = t:func(2)");
|
||||
val = lua["val"];
|
||||
|
|
Loading…
Reference in New Issue
Block a user