mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
New Unsafe Feature: Function Pointers!
- Not at all type safe: there should be some investigation into making it less unsafe to work with these things (albeit it looks like it would cost +1 pointer to serialize a string name for each callable in Lua, at LEAST) - Must be opted into - see the documentation - Fixes #1015 - A few drive-by fixes here and there - New configuration test harness with CMake
This commit is contained in:
parent
1fb483db91
commit
48eea7b573
|
@ -24,6 +24,7 @@ Okay, so the features don't convince you, the documentation doesn't convince you
|
|||
+----------+---------+
|
||||
|
||||
* In `Perforce`_ (later versions of the code using sol2 more directly can be requested by e-mailing support@perforce.com !)
|
||||
* For Sandboxing `Fun`_!
|
||||
* In `High Performance Computing research`_
|
||||
- `Published research, too!`_
|
||||
* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol3!
|
||||
|
@ -39,7 +40,7 @@ Okay, so the features don't convince you, the documentation doesn't convince you
|
|||
* (Twitter) Twitter has some people that link it:
|
||||
- The image above, `tweeted out by eevee`_
|
||||
- Eevee: `"I heartily recommend sol3"`_
|
||||
- Elias Daler: `"sol3 saved my life."`_
|
||||
- Elias Daler: `"sol2 is making usertypes in Lua so awesome <3"`_
|
||||
- Racod's Lair: `"from outdated LuaBridge to superior #sol3"`_
|
||||
* (Reddit) Posts on reddit about it!
|
||||
- `sol2's initial reddit release`_
|
||||
|
@ -52,12 +53,14 @@ Are you using sol3 for something neat? Want it to be featured here or think it's
|
|||
.. _tell me about your uses!: https://github.com/ThePhD/sol2/issues/189
|
||||
.. _eevee: https://twitter.com/eevee
|
||||
.. _eevee's blog: https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/
|
||||
.. _Fun: https://blog.rubenwardy.com/2020/07/26/sol3-script-sandbox/
|
||||
.. _Jason Turner's presentation: https://github.com/lefticus/presentations/blob/master/WhyAndHowToAddScripting.md
|
||||
.. _Elias Daler's blog: https://eliasdaler.github.io/cppcast#read-more
|
||||
.. _CppCast: http://cppcast.com/2016/07/elias-daler/
|
||||
.. _tweeted out by eevee: https://twitter.com/eevee/status/762039984085798913
|
||||
.. _"I heartily recommend sol3": https://twitter.com/eevee/status/762040086540144644
|
||||
.. _"from outdated LuaBridge to superior #sol3": https://twitter.com/racodslair/status/754031870640267264
|
||||
.. _"sol2 is making usertypes in Lua so awesome <3": https://twitter.com/EliasDaler/status/778708299029946368
|
||||
.. _sol2's initial reddit release: https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/
|
||||
.. _Benchmarking Discussing: https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/
|
||||
.. _"After spending hours with sol2, it wins. Amazing lib.": https://twitter.com/EliasDaler/status/739215685264494593
|
||||
|
|
|
@ -89,6 +89,14 @@ Feature Config
|
|||
* Includes ``<iostream>`` and prints all exceptions and errors to ``std::cerr``, for you to see
|
||||
* **Not** turned on by default under any settings: *this MUST be turned on manually*
|
||||
|
||||
``SOL_GET_FUNCTION_POINTERS_UNSAFE`` triggers 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::overload`` type checking and will not discriminate properly between function types
|
||||
- It **WILL** happily let you retrieve an ``int(*)(int, int int)`` from a ``void(*)()`` function pointer, and shatter your runtime if you call it
|
||||
* 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_START`` triggers 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)
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace sol {
|
|||
using type = T;
|
||||
};
|
||||
|
||||
struct call_indicator {};
|
||||
struct call_indicator { };
|
||||
|
||||
template <bool yielding>
|
||||
int lua_c_wrapper(lua_State* L) {
|
||||
|
@ -65,16 +65,15 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
|
||||
struct c_function_invocation {};
|
||||
struct c_function_invocation { };
|
||||
|
||||
template <bool is_yielding, typename Fx, typename... Args>
|
||||
void select(lua_State* L, Fx&& fx, Args&&... args);
|
||||
|
||||
template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
|
||||
void select_set_fx(lua_State* L, Args&&... args) {
|
||||
lua_CFunction freefunc = no_trampoline ?
|
||||
detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>
|
||||
: function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
|
||||
lua_CFunction freefunc = no_trampoline ? detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>
|
||||
: function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
|
||||
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
|
@ -680,7 +679,56 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
};
|
||||
} // namespace stack
|
||||
|
||||
namespace stack_detail {
|
||||
template <typename Function, typename Handler>
|
||||
bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
tracking.use(1);
|
||||
bool success = lua_iscfunction(L, index) == 1;
|
||||
if (success) {
|
||||
// there must be at LEAST 2 upvalues; otherwise, we didn't serialize it.
|
||||
const char* upvalue_name = lua_getupvalue(L, index, 2);
|
||||
lua_pop(L, 1);
|
||||
success = upvalue_name != nullptr;
|
||||
}
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(
|
||||
L, index, type::function, type_of(L, index), "type must be a Lua C Function gotten from a function pointer serialized by sol2");
|
||||
}
|
||||
return success;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
tracking.use(1);
|
||||
auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
|
||||
Function* fx = udata.first;
|
||||
return fx;
|
||||
#else
|
||||
static_assert(meta::meta_detail::always_true<Function>::value,
|
||||
#if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
"You are attempting to retrieve a function pointer type. "
|
||||
"This is inherently unsafe in sol2. In order to do this, you must turn on the "
|
||||
"SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. "
|
||||
"Please be careful!"
|
||||
#else
|
||||
"You are attempting to retrieve a function pointer type. "
|
||||
"You explicitly turned off the ability to do this by defining "
|
||||
"SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. "
|
||||
"Please reconsider this!"
|
||||
#endif
|
||||
);
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
} // namespace stack_detail
|
||||
} // namespace stack
|
||||
} // namespace sol
|
||||
|
||||
#endif // SOL_FUNCTION_TYPES_HPP
|
||||
|
|
|
@ -101,8 +101,9 @@ namespace sol {
|
|||
data_t data { {} };
|
||||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||
int pushcount = 0;
|
||||
for (auto&& v : data) {
|
||||
pushcount += push(L, lightuserdata_value(v));
|
||||
for (const auto& v : data) {
|
||||
lua_pushlightuserdata(L, v);
|
||||
pushcount += 1;
|
||||
}
|
||||
return pushcount;
|
||||
}
|
||||
|
@ -113,11 +114,33 @@ namespace sol {
|
|||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata { {} };
|
||||
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++));
|
||||
voiddata[i] = lua_touserdata(L, upvalue_index(index++));
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) {
|
||||
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
function_index = lua_absindex(L, function_index);
|
||||
int index = 0;
|
||||
data_t voiddata { {} };
|
||||
for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) {
|
||||
// first upvalue is nullptr to respect environment shenanigans
|
||||
// So +2 instead of +1
|
||||
const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
|
||||
if (upvalue_name == nullptr) {
|
||||
// We should freak out here...
|
||||
break;
|
||||
}
|
||||
voiddata[index] = lua_touserdata(L, -1);
|
||||
++index;
|
||||
}
|
||||
lua_pop(L, index);
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) {
|
||||
return std::forward<Fx>(fx)(std::forward<Args>(args)...);
|
||||
|
|
|
@ -348,6 +348,11 @@ namespace sol { namespace stack {
|
|||
}
|
||||
return stack::unqualified_check<ValueType>(L, index, no_panic, tracking);
|
||||
}
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
|
||||
return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
#endif
|
||||
else if constexpr (expected == type::userdata) {
|
||||
if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) {
|
||||
tracking.use(1);
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -178,7 +178,7 @@ namespace sol {
|
|||
return ptr;
|
||||
}
|
||||
std::size_t space = (std::numeric_limits<std::size_t>::max)();
|
||||
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||
return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -187,7 +187,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -195,7 +195,7 @@ namespace sol {
|
|||
return ptr;
|
||||
}
|
||||
std::size_t space = (std::numeric_limits<std::size_t>::max)();
|
||||
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||
return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -297,7 +297,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T*>::value > 1 || std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -436,7 +436,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -450,13 +450,13 @@ namespace sol {
|
|||
|
||||
std::size_t allocated_size = initial_size;
|
||||
void* unadjusted = lua_newuserdata(L, allocated_size);
|
||||
void* adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size);
|
||||
void* adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
|
||||
if (adjusted == nullptr) {
|
||||
lua_pop(L, 1);
|
||||
// try again, add extra space for alignment padding
|
||||
allocated_size = misaligned_size;
|
||||
unadjusted = lua_newuserdata(L, allocated_size);
|
||||
adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size);
|
||||
adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
|
||||
if (adjusted == nullptr) {
|
||||
lua_pop(L, 1);
|
||||
luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data());
|
||||
|
@ -630,14 +630,21 @@ namespace sol {
|
|||
int last;
|
||||
int used;
|
||||
|
||||
record() : last(), used() {
|
||||
record() noexcept : last(), used() {
|
||||
}
|
||||
void use(int count) {
|
||||
void use(int count) noexcept {
|
||||
last = count;
|
||||
used += count;
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack_detail {
|
||||
template <typename Function>
|
||||
Function* get_function_pointer(lua_State*, int, record&) noexcept;
|
||||
template <typename Function, typename Handler>
|
||||
bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept;
|
||||
} // namespace stack_detail
|
||||
|
||||
} // namespace stack
|
||||
|
||||
namespace meta { namespace meta_detail {
|
||||
|
|
|
@ -163,6 +163,11 @@ namespace sol { namespace stack {
|
|||
luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
|
||||
return *pstream;
|
||||
}
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
|
||||
return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
|
||||
}
|
||||
|
@ -949,10 +954,22 @@ namespace sol { namespace stack {
|
|||
template <typename T>
|
||||
struct unqualified_getter<T*> {
|
||||
static T* get(lua_State* L, int index, record& tracking) {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
if constexpr (std::is_function_v<T>) {
|
||||
return stack_detail::get_function_pointer<T>(L, index, tracking);
|
||||
}
|
||||
else {
|
||||
unqualified_getter<detail::as_pointer_tag<T>> g;
|
||||
// Avoid VC++ warning
|
||||
(void)g;
|
||||
return g.get(L, index, tracking);
|
||||
}
|
||||
#else
|
||||
unqualified_getter<detail::as_pointer_tag<T>> g;
|
||||
// Avoid VC++ warning
|
||||
(void)g;
|
||||
return g.get(L, index, tracking);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1077,13 +1077,21 @@ namespace sol {
|
|||
template <>
|
||||
struct lua_type_of<type> : std::integral_constant<type, type::poly> { };
|
||||
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
template <typename T>
|
||||
struct lua_type_of<T*> : std::integral_constant<type, std::is_function_v<T> ? type::function : type::userdata> { };
|
||||
#else
|
||||
template <typename T>
|
||||
struct lua_type_of<T*> : std::integral_constant<type, type::userdata> { };
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, lua_Number> || std::is_same_v<T, lua_Integer>>>
|
||||
: std::integral_constant<type, type::number> { };
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_function_v<T>>> : std::integral_constant<type, type::function> { };
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_enum_v<T>>> : std::integral_constant<type, type::number> { };
|
||||
|
||||
|
|
|
@ -563,6 +563,16 @@
|
|||
#define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON
|
||||
#endif
|
||||
|
||||
#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE)
|
||||
#if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0)
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF
|
||||
#endif
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF
|
||||
#endif
|
||||
|
||||
#if SOL_IS_ON(SOL_COMPILER_FRONTEND_MINGW_I_) && defined(__GNUC__) && (__GNUC__ < 6)
|
||||
// MinGW is off its rocker in some places...
|
||||
#define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON
|
||||
|
|
|
@ -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 2020-09-26 10:47:52.233754 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 000fa31)
|
||||
// Generated 2020-09-26 13:38:14.149661 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 1fb483d)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_CONFIG_HPP
|
||||
|
|
|
@ -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 2020-09-26 10:47:52.207756 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 000fa31)
|
||||
// Generated 2020-09-26 13:38:14.123663 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 1fb483d)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||
|
@ -569,6 +569,16 @@
|
|||
#define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON
|
||||
#endif
|
||||
|
||||
#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE)
|
||||
#if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0)
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF
|
||||
#endif
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF
|
||||
#endif
|
||||
|
||||
#if SOL_IS_ON(SOL_COMPILER_FRONTEND_MINGW_I_) && defined(__GNUC__) && (__GNUC__ < 6)
|
||||
// MinGW is off its rocker in some places...
|
||||
#define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON
|
||||
|
|
|
@ -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 2020-09-26 10:47:51.277755 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 000fa31)
|
||||
// Generated 2020-09-26 13:38:13.096661 UTC
|
||||
// This header was generated with sol v3.2.1 (revision 1fb483d)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -569,6 +569,16 @@
|
|||
#define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON
|
||||
#endif
|
||||
|
||||
#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE)
|
||||
#if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0)
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF
|
||||
#endif
|
||||
#else
|
||||
#define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF
|
||||
#endif
|
||||
|
||||
#if SOL_IS_ON(SOL_COMPILER_FRONTEND_MINGW_I_) && defined(__GNUC__) && (__GNUC__ < 6)
|
||||
// MinGW is off its rocker in some places...
|
||||
#define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON
|
||||
|
@ -7588,13 +7598,21 @@ namespace sol {
|
|||
template <>
|
||||
struct lua_type_of<type> : std::integral_constant<type, type::poly> { };
|
||||
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
template <typename T>
|
||||
struct lua_type_of<T*> : std::integral_constant<type, std::is_function_v<T> ? type::function : type::userdata> { };
|
||||
#else
|
||||
template <typename T>
|
||||
struct lua_type_of<T*> : std::integral_constant<type, type::userdata> { };
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, lua_Number> || std::is_same_v<T, lua_Integer>>>
|
||||
: std::integral_constant<type, type::number> { };
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_function_v<T>>> : std::integral_constant<type, type::function> { };
|
||||
|
||||
template <typename T>
|
||||
struct lua_type_of<T, std::enable_if_t<std::is_enum_v<T>>> : std::integral_constant<type, type::number> { };
|
||||
|
||||
|
@ -9849,7 +9867,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -9863,7 +9881,7 @@ namespace sol {
|
|||
return ptr;
|
||||
}
|
||||
std::size_t space = (std::numeric_limits<std::size_t>::max)();
|
||||
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||
return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -9872,7 +9890,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -9880,7 +9898,7 @@ namespace sol {
|
|||
return ptr;
|
||||
}
|
||||
std::size_t space = (std::numeric_limits<std::size_t>::max)();
|
||||
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||
return align(std::alignment_of_v<T>, sizeof(T), ptr, space);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -9982,7 +10000,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T*>::value > 1 || std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -10121,7 +10139,7 @@ namespace sol {
|
|||
#if SOL_IS_OFF(SOL_ALIGN_MEMORY_I_)
|
||||
false
|
||||
#else
|
||||
(std::alignment_of<T>::value > 1)
|
||||
(std::alignment_of_v<T> > 1)
|
||||
#endif
|
||||
>
|
||||
use_align;
|
||||
|
@ -10135,13 +10153,13 @@ namespace sol {
|
|||
|
||||
std::size_t allocated_size = initial_size;
|
||||
void* unadjusted = lua_newuserdata(L, allocated_size);
|
||||
void* adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size);
|
||||
void* adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
|
||||
if (adjusted == nullptr) {
|
||||
lua_pop(L, 1);
|
||||
// try again, add extra space for alignment padding
|
||||
allocated_size = misaligned_size;
|
||||
unadjusted = lua_newuserdata(L, allocated_size);
|
||||
adjusted = align(std::alignment_of<T>::value, sizeof(T), unadjusted, allocated_size);
|
||||
adjusted = align(std::alignment_of_v<T>, sizeof(T), unadjusted, allocated_size);
|
||||
if (adjusted == nullptr) {
|
||||
lua_pop(L, 1);
|
||||
luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data());
|
||||
|
@ -10315,14 +10333,21 @@ namespace sol {
|
|||
int last;
|
||||
int used;
|
||||
|
||||
record() : last(), used() {
|
||||
record() noexcept : last(), used() {
|
||||
}
|
||||
void use(int count) {
|
||||
void use(int count) noexcept {
|
||||
last = count;
|
||||
used += count;
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack_detail {
|
||||
template <typename Function>
|
||||
Function* get_function_pointer(lua_State*, int, record&) noexcept;
|
||||
template <typename Function, typename Handler>
|
||||
bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept;
|
||||
} // namespace stack_detail
|
||||
|
||||
} // namespace stack
|
||||
|
||||
namespace meta { namespace meta_detail {
|
||||
|
@ -11457,6 +11482,11 @@ namespace sol { namespace stack {
|
|||
}
|
||||
return stack::unqualified_check<ValueType>(L, index, no_panic, tracking);
|
||||
}
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
|
||||
return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
#endif
|
||||
else if constexpr (expected == type::userdata) {
|
||||
if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) {
|
||||
tracking.use(1);
|
||||
|
@ -12265,6 +12295,11 @@ namespace sol { namespace stack {
|
|||
luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index));
|
||||
return *pstream;
|
||||
}
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
|
||||
return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
|
||||
}
|
||||
|
@ -13051,10 +13086,22 @@ namespace sol { namespace stack {
|
|||
template <typename T>
|
||||
struct unqualified_getter<T*> {
|
||||
static T* get(lua_State* L, int index, record& tracking) {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
if constexpr (std::is_function_v<T>) {
|
||||
return stack_detail::get_function_pointer<T>(L, index, tracking);
|
||||
}
|
||||
else {
|
||||
unqualified_getter<detail::as_pointer_tag<T>> g;
|
||||
// Avoid VC++ warning
|
||||
(void)g;
|
||||
return g.get(L, index, tracking);
|
||||
}
|
||||
#else
|
||||
unqualified_getter<detail::as_pointer_tag<T>> g;
|
||||
// Avoid VC++ warning
|
||||
(void)g;
|
||||
return g.get(L, index, tracking);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -14936,8 +14983,9 @@ namespace sol {
|
|||
data_t data { {} };
|
||||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||
int pushcount = 0;
|
||||
for (auto&& v : data) {
|
||||
pushcount += push(L, lightuserdata_value(v));
|
||||
for (const auto& v : data) {
|
||||
lua_pushlightuserdata(L, v);
|
||||
pushcount += 1;
|
||||
}
|
||||
return pushcount;
|
||||
}
|
||||
|
@ -14948,11 +14996,33 @@ namespace sol {
|
|||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata { {} };
|
||||
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++));
|
||||
voiddata[i] = lua_touserdata(L, upvalue_index(index++));
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) {
|
||||
static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
function_index = lua_absindex(L, function_index);
|
||||
int index = 0;
|
||||
data_t voiddata { {} };
|
||||
for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) {
|
||||
// first upvalue is nullptr to respect environment shenanigans
|
||||
// So +2 instead of +1
|
||||
const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
|
||||
if (upvalue_name == nullptr) {
|
||||
// We should freak out here...
|
||||
break;
|
||||
}
|
||||
voiddata[index] = lua_touserdata(L, -1);
|
||||
++index;
|
||||
}
|
||||
lua_pop(L, index);
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) {
|
||||
return std::forward<Fx>(fx)(std::forward<Args>(args)...);
|
||||
|
@ -18120,7 +18190,7 @@ namespace sol {
|
|||
using type = T;
|
||||
};
|
||||
|
||||
struct call_indicator {};
|
||||
struct call_indicator { };
|
||||
|
||||
template <bool yielding>
|
||||
int lua_c_wrapper(lua_State* L) {
|
||||
|
@ -18146,16 +18216,15 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
|
||||
struct c_function_invocation {};
|
||||
struct c_function_invocation { };
|
||||
|
||||
template <bool is_yielding, typename Fx, typename... Args>
|
||||
void select(lua_State* L, Fx&& fx, Args&&... args);
|
||||
|
||||
template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
|
||||
void select_set_fx(lua_State* L, Args&&... args) {
|
||||
lua_CFunction freefunc = no_trampoline ?
|
||||
detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>
|
||||
: function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
|
||||
lua_CFunction freefunc = no_trampoline ? detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>
|
||||
: function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
|
||||
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
|
@ -18761,7 +18830,56 @@ namespace sol {
|
|||
}
|
||||
}
|
||||
};
|
||||
} // namespace stack
|
||||
|
||||
namespace stack_detail {
|
||||
template <typename Function, typename Handler>
|
||||
bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
tracking.use(1);
|
||||
bool success = lua_iscfunction(L, index) == 1;
|
||||
if (success) {
|
||||
// there must be at LEAST 2 upvalues; otherwise, we didn't serialize it.
|
||||
const char* upvalue_name = lua_getupvalue(L, index, 2);
|
||||
lua_pop(L, 1);
|
||||
success = upvalue_name != nullptr;
|
||||
}
|
||||
if (!success) {
|
||||
// expected type, actual type
|
||||
handler(
|
||||
L, index, type::function, type_of(L, index), "type must be a Lua C Function gotten from a function pointer serialized by sol2");
|
||||
}
|
||||
return success;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept {
|
||||
#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
tracking.use(1);
|
||||
auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
|
||||
Function* fx = udata.first;
|
||||
return fx;
|
||||
#else
|
||||
static_assert(meta::meta_detail::always_true<Function>::value,
|
||||
#if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE_I_)
|
||||
"You are attempting to retrieve a function pointer type. "
|
||||
"This is inherently unsafe in sol2. In order to do this, you must turn on the "
|
||||
"SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. "
|
||||
"Please be careful!"
|
||||
#else
|
||||
"You are attempting to retrieve a function pointer type. "
|
||||
"You explicitly turned off the ability to do this by defining "
|
||||
"SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. "
|
||||
"Please reconsider this!"
|
||||
#endif
|
||||
);
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
} // namespace stack_detail
|
||||
} // namespace stack
|
||||
} // namespace sol
|
||||
|
||||
// end of sol/function_types.hpp
|
||||
|
|
|
@ -24,4 +24,5 @@
|
|||
|
||||
add_subdirectory(runtime_tests)
|
||||
add_subdirectory(compile_tests)
|
||||
add_subdirectory(config_tests)
|
||||
add_subdirectory(regression_tests)
|
||||
|
|
25
tests/config_tests/CMakeLists.txt
Normal file
25
tests/config_tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
# # # # sol3
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2013-2020 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.
|
||||
|
||||
# # # # sol3 tests
|
||||
|
||||
add_subdirectory(function_pointers)
|
103
tests/config_tests/function_pointers/CMakeLists.txt
Normal file
103
tests/config_tests/function_pointers/CMakeLists.txt
Normal file
|
@ -0,0 +1,103 @@
|
|||
# # # # sol3
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2013-2020 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.
|
||||
|
||||
# # # # sol3 tests - simple regression tests
|
||||
|
||||
file(GLOB test_sources source/*.cpp)
|
||||
source_group(sources FILES ${test_sources})
|
||||
|
||||
function(CREATE_TEST test_target_name test_name target_sol)
|
||||
add_executable(${test_target_name} ${test_sources})
|
||||
set_target_properties(${test_target_name}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME ${test_name}
|
||||
EXPORT_NAME sol2::${test_name})
|
||||
target_link_libraries(${test_target_name}
|
||||
PUBLIC Threads::Threads ${LUA_LIBRARIES} ${target_sol})
|
||||
target_compile_definitions(${test_target_name}
|
||||
PRIVATE SOL_GET_FUNCTION_POINTER_UNSAFE=1 SOL_ALL_SAFETIES_ON=1)
|
||||
target_include_directories(${test_target_name}
|
||||
PRIVATE ../../../examples/include)
|
||||
|
||||
if (MSVC)
|
||||
if (NOT CMAKE_COMPILER_ID MATCHES "Clang")
|
||||
target_compile_options(${test_target_name}
|
||||
PRIVATE /bigobj /W4)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(${test_target_name}
|
||||
PRIVATE -std=c++1z -pthread
|
||||
-Wno-unknown-warning -Wno-unknown-warning-option
|
||||
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
|
||||
-Wno-noexcept-type)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# For another day, when C++ is not so crap
|
||||
# and we have time to audit the entire lib
|
||||
# for all uses of `detail::swallow`...
|
||||
#target_compile_options(${test_target_name}
|
||||
# PRIVATE -Wcomma)
|
||||
endif()
|
||||
|
||||
if (IS_X86)
|
||||
if(MINGW)
|
||||
set_target_properties(${test_target_name}
|
||||
PROPERTIES
|
||||
LINK_FLAGS -static-libstdc++)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if (MSVC)
|
||||
target_compile_options(${test_target_name}
|
||||
PRIVATE /EHsc /std:c++latest)
|
||||
target_compile_definitions(${test_target_name}
|
||||
PRIVATE UNICODE _UNICODE
|
||||
_CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE)
|
||||
else()
|
||||
target_compile_options(${test_target_name}
|
||||
PRIVATE -std=c++1z -Wno-unknown-warning -Wno-unknown-warning-option
|
||||
-Wall -Wextra -Wpedantic -pedantic -pedantic-errors)
|
||||
endif()
|
||||
|
||||
if (SOL2_CI)
|
||||
target_compile_definitions(${test_target_name}
|
||||
PRIVATE SOL2_CI)
|
||||
endif()
|
||||
|
||||
if (CMAKE_DL_LIBS)
|
||||
target_link_libraries(${test_target_name}
|
||||
PRIVATE ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
add_test(NAME ${test_name} COMMAND ${test_target_name})
|
||||
install(TARGETS ${test_target_name} RUNTIME DESTINATION bin)
|
||||
endfunction(CREATE_TEST)
|
||||
|
||||
if (SOL2_TESTS)
|
||||
CREATE_TEST(config_function_pointers_tests "config_function_pointers_tests" sol2::sol2)
|
||||
endif()
|
||||
if (SOL2_TESTS_SINGLE)
|
||||
CREATE_TEST(config_function_pointers_tests_single "config_function_pointers_tests.single" sol2::sol2_single)
|
||||
endif()
|
||||
if (SOL2_TESTS_SINGLE_GENERATED)
|
||||
CREATE_TEST(config_function_pointers_tests_generated_single "config_function_pointers_tests.single.generated" sol2::sol2_single_generated)
|
||||
endif()
|
74
tests/config_tests/function_pointers/source/main.cpp
Normal file
74
tests/config_tests/function_pointers/source/main.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include <sol/sol.hpp>
|
||||
|
||||
#include <assert.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
inline constexpr int magic_value = 24;
|
||||
|
||||
using zero_arg_type = int (*)();
|
||||
using one_arg_type = int (*)(int);
|
||||
using callback_type = int (*)(one_arg_type);
|
||||
|
||||
int free_function(int value) {
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
int callback(one_arg_type f) {
|
||||
return f(magic_value) + 1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
constexpr int expected_value = magic_value;
|
||||
constexpr int expected_free_function_value = magic_value + 1;
|
||||
constexpr int expected_callback_value = magic_value + 1 + 1;
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
auto lambda = []() { return magic_value; };
|
||||
auto lambda_ptr = static_cast<zero_arg_type>(lambda);
|
||||
|
||||
lua["magic_value"] = magic_value;
|
||||
lua["expected_value"] = expected_value;
|
||||
lua["expected_free_function_value"] = expected_free_function_value;
|
||||
lua["expected_callback_value"] = expected_callback_value;
|
||||
|
||||
lua["lambda"] = sol::as_function_reference(lambda);
|
||||
lua["lambda_ptr"] = lambda_ptr;
|
||||
lua["free_function"] = &free_function;
|
||||
lua["callback"] = &callback;
|
||||
|
||||
zero_arg_type lambda_f = lua["lambda"];
|
||||
zero_arg_type lambda_ptr_f = lua["lambda_ptr"];
|
||||
one_arg_type free_function_f = lua["free_function"];
|
||||
callback_type callback_f = lua["callback"];
|
||||
sol::function lua_callback_f = lua["callback"];
|
||||
|
||||
int lambda_f_result = lambda_f();
|
||||
int lambda_ptr_f_result = lambda_ptr_f();
|
||||
int free_function_f_result = free_function_f(magic_value);
|
||||
int callback_f_result = callback_f(&free_function);
|
||||
int lua_callback_f_result = lua_callback_f(&free_function);
|
||||
c_assert(lambda_f_result == expected_value);
|
||||
c_assert(lambda_ptr_f_result == expected_value);
|
||||
c_assert(free_function_f_result == expected_free_function_value);
|
||||
c_assert(callback_f_result == expected_callback_value);
|
||||
c_assert(lua_callback_f_result == expected_callback_value);
|
||||
|
||||
const char code[] = R"(
|
||||
assert(lambda() == expected_value)
|
||||
assert(lambda_ptr() == expected_value)
|
||||
assert(free_function(magic_value) == expected_free_function_value)
|
||||
assert(callback(free_function) == expected_callback_value)
|
||||
)";
|
||||
|
||||
sol::optional<sol::error> err = lua.safe_script(code, sol::script_pass_on_error);
|
||||
if (err.has_value()) {
|
||||
std::cerr << err.value().what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
c_assert(!err.has_value());
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user