mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
V E T T E D
Slight breaking change, but at the source level almost nothing changes (ipairs is the only thing that changes because for some reason it checks if what is passed is a table and that really doesn't make any fucking sense) Closes #195 Closes #196
This commit is contained in:
parent
ffe6e79f97
commit
cf76f6baa0
|
@ -7,7 +7,7 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Sol API
|
:caption: Sol API
|
||||||
:name: apitoc
|
:name: apitoc
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
|
|
||||||
compatibility
|
compatibility
|
||||||
coroutine
|
coroutine
|
||||||
|
|
|
@ -22,7 +22,7 @@ get going:
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
:name: mastertoc
|
:name: mastertoc
|
||||||
|
|
||||||
tutorial/all-the-things
|
tutorial/all-the-things
|
||||||
|
|
|
@ -7,7 +7,7 @@ Take some time to learn the framework with thse tutorials. But, if you need to g
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Sol Tutorial
|
:caption: Sol Tutorial
|
||||||
:name: tutorialtoc
|
:name: tutorialtoc
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
|
|
||||||
all-the-things
|
all-the-things
|
||||||
getting-started
|
getting-started
|
||||||
|
|
18
sol/call.hpp
18
sol/call.hpp
|
@ -61,14 +61,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline int destruct(lua_State* L) {
|
|
||||||
T* obj = stack::get<non_null<T*>>(L, 1);
|
|
||||||
std::allocator<T> alloc{};
|
|
||||||
alloc.destroy(obj);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace overload_detail {
|
namespace overload_detail {
|
||||||
template <std::size_t... M, typename Match, typename... Args>
|
template <std::size_t... M, typename Match, typename... Args>
|
||||||
inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
||||||
|
@ -251,7 +243,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return call(L, std::forward<Fx>(f), *o);
|
return call(L, std::forward<Fx>(f), *o);
|
||||||
#else
|
#else
|
||||||
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
|
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
|
||||||
return call(L, std::forward<Fx>(f), o);
|
return call(L, std::forward<Fx>(f), o);
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
|
@ -283,7 +275,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return call_assign(std::true_type(), L, f, *o);
|
return call_assign(std::true_type(), L, f, *o);
|
||||||
#else
|
#else
|
||||||
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
|
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
|
||||||
return call_assign(std::true_type(), L, f, o);
|
return call_assign(std::true_type(), L, f, o);
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
|
@ -341,7 +333,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
return call(L, f, *o);
|
return call(L, f, *o);
|
||||||
#else
|
#else
|
||||||
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
|
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
|
||||||
return call(L, f, o);
|
return call(L, f, o);
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
|
@ -422,7 +414,7 @@ namespace sol {
|
||||||
typedef destructor_wrapper<Fx> F;
|
typedef destructor_wrapper<Fx> F;
|
||||||
|
|
||||||
static int call(lua_State* L, const F&) {
|
static int call(lua_State* L, const F&) {
|
||||||
return destruct<T>(L);
|
return detail::usertype_alloc_destroy<T>(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -493,7 +485,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
object_type& o = *po;
|
object_type& o = *po;
|
||||||
#else
|
#else
|
||||||
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
|
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
typedef typename wrap::returns_list returns_list;
|
typedef typename wrap::returns_list returns_list;
|
||||||
typedef typename wrap::caller caller;
|
typedef typename wrap::caller caller;
|
||||||
|
|
393
sol/container_usertype_metatable.hpp
Normal file
393
sol/container_usertype_metatable.hpp
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef SOL_CONTAINER_USERTYPE_HPP
|
||||||
|
#define SOL_CONTAINER_USERTYPE_HPP
|
||||||
|
|
||||||
|
#include "stack.hpp"
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_find {
|
||||||
|
private:
|
||||||
|
typedef std::array<char, 1> one;
|
||||||
|
typedef std::array<char, 2> two;
|
||||||
|
|
||||||
|
template <typename C> static one test(decltype(&C::find));
|
||||||
|
template <typename C> static two test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool value = sizeof(test<T>(0)) == sizeof(char);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& get_first(const T& t) {
|
||||||
|
return std::forward<T>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
decltype(auto) get_first(const std::pair<A, B>& t) {
|
||||||
|
return t.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C, typename I, meta::enable<has_find<meta::unqualified_t<C>>> = meta::enabler>
|
||||||
|
auto find(C& c, I&& i) {
|
||||||
|
return c.find(std::forward<I>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C, typename I, meta::disable<has_find<meta::unqualified_t<C>>> = meta::enabler>
|
||||||
|
auto find(C& c, I&& i) {
|
||||||
|
using std::begin;
|
||||||
|
using std::end;
|
||||||
|
return std::find_if(begin(c), end(c), [&i](auto&& x) {
|
||||||
|
return i == get_first(x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename C = void>
|
||||||
|
struct container_usertype_metatable {
|
||||||
|
typedef meta::unqualified_t<T> U;
|
||||||
|
typedef std::size_t K;
|
||||||
|
typedef typename U::value_type V;
|
||||||
|
typedef typename U::iterator I;
|
||||||
|
struct iter {
|
||||||
|
U& source;
|
||||||
|
I it;
|
||||||
|
|
||||||
|
iter(U& source, I it) : source(source), it(std::move(it)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto& get_src(lua_State* L) {
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
auto p = stack::get<T*>(L, 1);
|
||||||
|
if (p == nullptr) {
|
||||||
|
luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)");
|
||||||
|
}
|
||||||
|
return *p;
|
||||||
|
#else
|
||||||
|
return stack::get<T>(L, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_index_call(lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
|
if (maybek) {
|
||||||
|
using std::begin;
|
||||||
|
auto it = begin(src);
|
||||||
|
K k = *maybek;
|
||||||
|
if (k <= src.size() && k > 0) {
|
||||||
|
--k;
|
||||||
|
std::advance(it, k);
|
||||||
|
return stack::push(L, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack::push(L, nil);
|
||||||
|
#else
|
||||||
|
using std::begin;
|
||||||
|
auto it = begin(src);
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
--k;
|
||||||
|
std::advance(it, k);
|
||||||
|
return stack::push(L, *it);
|
||||||
|
#endif // Safety
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::false_type, lua_State* L) {
|
||||||
|
luaL_error(L, "sol: cannot write to a const value type");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::true_type, lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
|
if (maybek) {
|
||||||
|
K k = *maybek;
|
||||||
|
if (k <= src.size() && k > 0) {
|
||||||
|
--k;
|
||||||
|
using std::begin;
|
||||||
|
auto it = begin(src);
|
||||||
|
std::advance(it, k);
|
||||||
|
*it = stack::get<V>(L, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
using std::begin;
|
||||||
|
auto it = begin(src);
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
--k;
|
||||||
|
std::advance(it, k);
|
||||||
|
*it = stack::get<V>(L, 3);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call(lua_State* L) {
|
||||||
|
return real_new_index_call_const(meta::neg<std::is_const<V>>(), L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_pairs_next_call(lua_State* L) {
|
||||||
|
using std::end;
|
||||||
|
iter& i = stack::get<user<iter>>(L, 1);
|
||||||
|
auto& source = i.source;
|
||||||
|
auto& it = i.it;
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
if (it == end(source)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int p = stack::push(L, k + 1);
|
||||||
|
p += stack::push(L, *it);
|
||||||
|
std::advance(it, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_pairs_call(lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
using std::begin;
|
||||||
|
stack::push(L, pairs_next_call);
|
||||||
|
stack::push<user<iter>>(L, src, begin(src));
|
||||||
|
stack::push(L, 0);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_length_call(lua_State*L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
return stack::push(L, src.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int real_push_back_call(lua_State*L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
src.push_back(stack::get<V>(L, 2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_insert_call(lua_State*L) {
|
||||||
|
using std::begin;
|
||||||
|
auto& src = get_src(L);
|
||||||
|
src.insert(std::next(begin(src), stack::get<K>(L, 2)), stack::get<V>(L, 3));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push_back_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_length_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int insert_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_insert_call)>(L);
|
||||||
|
}
|
||||||
|
#endif // Sometime later, in a distant universe...
|
||||||
|
|
||||||
|
static int length_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_length_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pairs_next_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_pairs_next_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pairs_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_pairs_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int index_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_index_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int new_index_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_new_index_call)>(L);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct container_usertype_metatable<T, std::enable_if_t<meta::has_key_value_pair<T>::value>> {
|
||||||
|
typedef meta::unqualified_t<T> U;
|
||||||
|
typedef typename U::value_type KV;
|
||||||
|
typedef typename KV::first_type K;
|
||||||
|
typedef typename KV::second_type V;
|
||||||
|
typedef typename U::iterator I;
|
||||||
|
struct iter {
|
||||||
|
U& source;
|
||||||
|
I it;
|
||||||
|
|
||||||
|
iter(U& source, I it) : source(source), it(std::move(it)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto& get_src(lua_State* L) {
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
auto p = stack::get<T*>(L, 1);
|
||||||
|
if (p == nullptr) {
|
||||||
|
luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)");
|
||||||
|
}
|
||||||
|
return *p;
|
||||||
|
#else
|
||||||
|
return stack::get<T>(L, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_index_call(lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
auto k = stack::check_get<K>(L, 2);
|
||||||
|
if (k) {
|
||||||
|
using std::end;
|
||||||
|
auto it = detail::find(src, *k);
|
||||||
|
if (it != end(src)) {
|
||||||
|
auto& v = *it;
|
||||||
|
return stack::push(L, v.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack::push(L, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::false_type, lua_State* L) {
|
||||||
|
luaL_error(L, "sol: cannot write to a const value type");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::true_type, lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
auto k = stack::check_get<K>(L, 2);
|
||||||
|
if (k) {
|
||||||
|
using std::end;
|
||||||
|
auto it = detail::find(src, *k);
|
||||||
|
if (it != end(src)) {
|
||||||
|
auto& v = *it;
|
||||||
|
v.second = stack::get<V>(L, 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
src.insert(it, { std::move(*k), stack::get<V>(L, 3) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call(lua_State* L) {
|
||||||
|
return real_new_index_call_const(meta::neg<std::is_const<V>>(), L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_pairs_next_call(lua_State* L) {
|
||||||
|
using std::end;
|
||||||
|
iter& i = stack::get<user<iter>>(L, 1);
|
||||||
|
auto& source = i.source;
|
||||||
|
auto& it = i.it;
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
std::advance(it, 1);
|
||||||
|
if (it == end(source)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return stack::multi_push_reference(L, it->first, it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_pairs_call(lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
using std::begin;
|
||||||
|
stack::push(L, pairs_next_call);
|
||||||
|
stack::push<user<iter>>(L, src, begin(src));
|
||||||
|
stack::push(L, 1);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_length_call(lua_State*L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
return stack::push(L, src.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int length_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_length_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pairs_next_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_pairs_next_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pairs_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_pairs_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int index_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_index_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int new_index_call(lua_State*L) {
|
||||||
|
return detail::static_trampoline<(&real_new_index_call)>(L);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace stack {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
||||||
|
typedef container_usertype_metatable<T> cumt;
|
||||||
|
template <typename C>
|
||||||
|
static int push(lua_State* L, C&& cont) {
|
||||||
|
auto fx = [&L]() {
|
||||||
|
const char* metakey = &usertype_traits<T>::metatable[0];
|
||||||
|
if (luaL_newmetatable(L, metakey) == 1) {
|
||||||
|
luaL_Reg reg[] = {
|
||||||
|
{ "__index", &cumt::index_call },
|
||||||
|
{ "__newindex", &cumt::new_index_call },
|
||||||
|
{ "__pairs", &cumt::pairs_call },
|
||||||
|
{ "__len", &cumt::length_call },
|
||||||
|
{ "__gc", &detail::usertype_alloc_destroy<T> },
|
||||||
|
{ nullptr, nullptr }
|
||||||
|
};
|
||||||
|
luaL_setfuncs(L, reg, 0);
|
||||||
|
}
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
};
|
||||||
|
return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::forward<C>(cont));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<T*, std::enable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
|
||||||
|
typedef container_usertype_metatable<T> cumt;
|
||||||
|
template <typename C>
|
||||||
|
static int push(lua_State* L, C&& cont) {
|
||||||
|
auto fx = [&L]() {
|
||||||
|
const char* metakey = &usertype_traits<meta::unqualified_t<T>*>::metatable[0];
|
||||||
|
if (luaL_newmetatable(L, metakey) == 1) {
|
||||||
|
luaL_Reg reg[] = {
|
||||||
|
{ "__index", &cumt::index_call },
|
||||||
|
{ "__newindex", &cumt::new_index_call },
|
||||||
|
{ "__pairs", &cumt::pairs_call },
|
||||||
|
{ "__len", &cumt::length_call },
|
||||||
|
{ nullptr, nullptr }
|
||||||
|
};
|
||||||
|
luaL_setfuncs(L, reg, 0);
|
||||||
|
}
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
};
|
||||||
|
return pusher<detail::as_pointer_tag<meta::unqualified_t<T>>>{}.push_fx(L, fx, std::forward<C>(cont));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // stack
|
||||||
|
|
||||||
|
} // sol
|
||||||
|
|
||||||
|
#endif // SOL_CONTAINER_USERTYPE_HPP
|
|
@ -31,18 +31,6 @@
|
||||||
#include "call.hpp"
|
#include "call.hpp"
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
template <typename Sig, typename... Ps>
|
|
||||||
struct function_arguments {
|
|
||||||
std::tuple<Ps...> params;
|
|
||||||
template <typename... Args>
|
|
||||||
function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Sig = function_sig<>, typename... Args>
|
|
||||||
function_arguments<Sig, Args...> as_function(Args&&... args) {
|
|
||||||
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template<typename... Sigs>
|
template<typename... Sigs>
|
||||||
struct pusher<function_sig<Sigs...>> {
|
struct pusher<function_sig<Sigs...>> {
|
||||||
|
@ -318,7 +306,7 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct pusher<detail::tagged<T, destructor_wrapper<void>>> {
|
struct pusher<detail::tagged<T, destructor_wrapper<void>>> {
|
||||||
static int push(lua_State* L, detail::tagged<T, destructor_wrapper<void>>) {
|
static int push(lua_State* L, detail::tagged<T, destructor_wrapper<void>>) {
|
||||||
lua_CFunction cf = call_detail::destruct<T>;
|
lua_CFunction cf = detail::user_alloc_destroy<T>;
|
||||||
return stack::push(L, cf);
|
return stack::push(L, cf);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct as_reference_tag {};
|
struct as_reference_tag {};
|
||||||
|
template <typename T>
|
||||||
|
struct as_pointer_tag {};
|
||||||
|
template <typename T>
|
||||||
|
struct as_value_tag {};
|
||||||
|
|
||||||
using special_destruct_func = void(*)(void*);
|
using special_destruct_func = void(*)(void*);
|
||||||
|
|
||||||
|
@ -55,6 +59,25 @@ namespace sol {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline int user_alloc_destroy(lua_State* L) {
|
||||||
|
void* rawdata = lua_touserdata(L, upvalue_index(1));
|
||||||
|
T* data = static_cast<T*>(rawdata);
|
||||||
|
std::allocator<T> alloc;
|
||||||
|
alloc.destroy(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline int usertype_alloc_destroy(lua_State* L) {
|
||||||
|
void* rawdata = lua_touserdata(L, 1);
|
||||||
|
T** pdata = static_cast<T**>(rawdata);
|
||||||
|
T* data = *pdata;
|
||||||
|
std::allocator<T> alloc{};
|
||||||
|
alloc.destroy(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void reserve(T&, std::size_t) {}
|
void reserve(T&, std::size_t) {}
|
||||||
|
|
||||||
|
@ -248,15 +271,6 @@ namespace sol {
|
||||||
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
return stack_detail::unchecked_get<optional<T>>(L, index, tracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline int alloc_destroy(lua_State* L) {
|
|
||||||
void* rawdata = lua_touserdata(L, upvalue_index(1));
|
|
||||||
T* data = static_cast<T*>(rawdata);
|
|
||||||
std::allocator<T> alloc;
|
|
||||||
alloc.destroy(data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool b>
|
template <bool b>
|
||||||
struct check_types {
|
struct check_types {
|
||||||
template <typename T, typename... Args, typename Handler>
|
template <typename T, typename... Args, typename Handler>
|
||||||
|
|
|
@ -132,7 +132,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T, bool, bool, typename>
|
template <typename T, bool, bool, typename>
|
||||||
struct field_setter {
|
struct field_setter {
|
||||||
template <typename Key, typename Value>
|
template <typename Key, typename Value>
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct getter<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
struct getter<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<T>>::value>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static T get(lua_State* L, int index, record& tracking) {
|
||||||
typedef typename T::value_type V;
|
typedef typename T::value_type V;
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
|
@ -88,45 +88,53 @@ namespace sol {
|
||||||
get_field<false, true>(L, static_cast<lua_Integer>(-1), index);
|
get_field<false, true>(L, static_cast<lua_Integer>(-1), index);
|
||||||
int isnum;
|
int isnum;
|
||||||
std::size_t sizehint = static_cast<std::size_t>(lua_tointegerx(L, -1, &isnum));
|
std::size_t sizehint = static_cast<std::size_t>(lua_tointegerx(L, -1, &isnum));
|
||||||
if (isnum == 0) {
|
if (isnum != 0) {
|
||||||
detail::reserve(arr, sizehint);
|
detail::reserve(arr, sizehint);
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
#if SOL_LUA_VERSION >= 503
|
#if SOL_LUA_VERSION >= 503
|
||||||
// This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3
|
// This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3
|
||||||
for (lua_Integer i = 0; ; ++i, lua_pop(L, 1)) {
|
for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
|
||||||
type t = static_cast<type>(lua_geti(L, index, i));
|
for (int vi = 0; vi < lua_size<V>::value; ++vi) {
|
||||||
if (t == type::nil) {
|
type t = static_cast<type>(lua_geti(L, index, i + vi));
|
||||||
if (i == 0)
|
if (t == type::nil) {
|
||||||
continue;
|
if (i == 0) {
|
||||||
else
|
continue;
|
||||||
break;
|
}
|
||||||
|
else {
|
||||||
|
lua_pop(L, (vi + 1));
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
arr.push_back(stack::get<V>(L, -1));
|
arr.push_back(stack::get<V>(L, -lua_size<V>::value));
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
|
||||||
#else
|
#else
|
||||||
// Zzzz slower but necessary thanks to the lower version API and missing functions qq
|
// Zzzz slower but necessary thanks to the lower version API and missing functions qq
|
||||||
for (lua_Integer i = 0; ; ++i, lua_pop(L, 1)) {
|
for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) {
|
||||||
lua_pushinteger(L, i);
|
for (int vi = 0; vi < lua_size<V>::value; ++vi) {
|
||||||
lua_gettable(L, index);
|
lua_pushinteger(L, i);
|
||||||
type t = type_of(L, -1);
|
lua_gettable(L, index);
|
||||||
if (t == type::nil) {
|
type t = type_of(L, -1);
|
||||||
if (i == 0)
|
if (t == type::nil) {
|
||||||
continue;
|
if (i == 0) {
|
||||||
else
|
continue;
|
||||||
break;
|
}
|
||||||
|
else {
|
||||||
|
lua_pop(L, (vi + 1));
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
arr.push_back(stack::get<V>(L, -1));
|
arr.push_back(stack::get<V>(L, -1));
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
|
||||||
#endif
|
#endif
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct getter<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
struct getter<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<T>>::value>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static T get(lua_State* L, int index, record& tracking) {
|
||||||
typedef typename T::value_type P;
|
typedef typename T::value_type P;
|
||||||
typedef typename P::first_type K;
|
typedef typename P::first_type K;
|
||||||
|
|
|
@ -33,10 +33,10 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template<typename T, typename>
|
template <typename T>
|
||||||
struct pusher {
|
struct pusher<detail::as_value_tag<T>> {
|
||||||
template <typename K, typename... Args>
|
template <typename F, typename... Args>
|
||||||
static int push_keyed(lua_State* L, K&& k, Args&&... args) {
|
static int push_fx(lua_State* L, F&& f, Args&&... args) {
|
||||||
// Basically, we store all user-data like this:
|
// Basically, we store all user-data like this:
|
||||||
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
||||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||||
|
@ -48,30 +48,44 @@ namespace sol {
|
||||||
referencereference = allocationtarget;
|
referencereference = allocationtarget;
|
||||||
std::allocator<T> alloc{};
|
std::allocator<T> alloc{};
|
||||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||||
luaL_newmetatable(L, &k[0]);
|
f();
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename K, typename... Args>
|
||||||
|
static int push_keyed(lua_State* L, K&& k, Args&&... args) {
|
||||||
|
return push_fx(L, [&L, &k]() {
|
||||||
|
luaL_newmetatable(L, &k[0]);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
}, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push(lua_State* L, Args&&... args) {
|
static int push(lua_State* L, Args&&... args) {
|
||||||
return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...);
|
return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct pusher<T*> {
|
struct pusher<detail::as_pointer_tag<T>> {
|
||||||
template <typename K>
|
template <typename F>
|
||||||
static int push_keyed(lua_State* L, K&& k, T* obj) {
|
static int push_fx(lua_State* L, F&& f, T* obj) {
|
||||||
if (obj == nullptr)
|
if (obj == nullptr)
|
||||||
return stack::push(L, nil);
|
return stack::push(L, nil);
|
||||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||||
*pref = obj;
|
*pref = obj;
|
||||||
luaL_newmetatable(L, &k[0]);
|
f();
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
static int push_keyed(lua_State* L, K&& k, T* obj) {
|
||||||
|
return push_fx(L, [&L, &k]() {
|
||||||
|
luaL_newmetatable(L, &k[0]);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
}, obj);
|
||||||
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, T* obj) {
|
static int push(lua_State* L, T* obj) {
|
||||||
return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable, obj);
|
return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable, obj);
|
||||||
}
|
}
|
||||||
|
@ -85,6 +99,22 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, typename>
|
||||||
|
struct pusher {
|
||||||
|
template <typename... Args>
|
||||||
|
static int push(lua_State* L, Args&&... args) {
|
||||||
|
return pusher<detail::as_value_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<T*, meta::disable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
|
||||||
|
template <typename... Args>
|
||||||
|
static int push(lua_State* L, Args&&... args) {
|
||||||
|
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> {
|
struct pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> {
|
||||||
typedef typename unique_usertype_traits<T>::type P;
|
typedef typename unique_usertype_traits<T>::type P;
|
||||||
|
@ -160,13 +190,37 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
struct pusher<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> {
|
||||||
static int push(lua_State* L, const T& cont) {
|
static int push(lua_State* L, const as_table_t<T>& tablecont) {
|
||||||
|
auto& cont = detail::deref(detail::unwrap(tablecont.source));
|
||||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||||
int tableindex = lua_gettop(L);
|
int tableindex = lua_gettop(L);
|
||||||
unsigned index = 1;
|
std::size_t index = 1;
|
||||||
for (auto&& i : cont) {
|
for (const auto& i : cont) {
|
||||||
set_field(L, index++, i, tableindex);
|
#if SOL_LUA_VERSION >= 503
|
||||||
|
int p = stack::push(L, i);
|
||||||
|
for (int pi = 0; pi < p; ++pi) {
|
||||||
|
lua_seti(L, tableindex, static_cast<lua_Integer>(index++));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
lua_pushinteger(L, static_cast<lua_Integer>(index));
|
||||||
|
int p = stack::push(L, i);
|
||||||
|
if (p == 1) {
|
||||||
|
++index;
|
||||||
|
lua_settable(L, tableindex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int firstindex = tableindex + 1 + 1;
|
||||||
|
for (int pi = 0; pi < p; ++pi) {
|
||||||
|
stack::push(L, index);
|
||||||
|
lua_pushvalue(L, firstindex);
|
||||||
|
lua_settable(L, tableindex);
|
||||||
|
++index;
|
||||||
|
++firstindex;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1 + p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
set_field(L, -1, cont.size());
|
set_field(L, -1, cont.size());
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -174,11 +228,12 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
struct pusher<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> {
|
||||||
static int push(lua_State* L, const T& cont) {
|
static int push(lua_State* L, const as_table_t<T>& tablecont) {
|
||||||
|
auto& cont = detail::deref(detail::unwrap(tablecont.source));
|
||||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||||
int tableindex = lua_gettop(L);
|
int tableindex = lua_gettop(L);
|
||||||
for (auto&& pair : cont) {
|
for (const auto& pair : cont) {
|
||||||
set_field(L, pair.first, pair.second, tableindex);
|
set_field(L, pair.first, pair.second, tableindex);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -292,7 +347,7 @@ namespace sol {
|
||||||
std::allocator<T> alloc;
|
std::allocator<T> alloc;
|
||||||
alloc.construct(data, std::forward<Args>(args)...);
|
alloc.construct(data, std::forward<Args>(args)...);
|
||||||
if (with_meta) {
|
if (with_meta) {
|
||||||
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
lua_CFunction cdel = detail::user_alloc_destroy<T>;
|
||||||
// Make sure we have a plain GC set for this data
|
// Make sure we have a plain GC set for this data
|
||||||
if (luaL_newmetatable(L, name) != 0) {
|
if (luaL_newmetatable(L, name) != 0) {
|
||||||
lua_pushlightuserdata(L, rawdata);
|
lua_pushlightuserdata(L, rawdata);
|
||||||
|
|
|
@ -317,7 +317,8 @@ namespace sol {
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
return lua_rawlen(base_t::lua_state(), -1);
|
lua_len(base_t::lua_state(), -1);
|
||||||
|
return stack::pop<size_t>(base_t::lua_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
|
|
|
@ -127,6 +127,9 @@ namespace sol {
|
||||||
|
|
||||||
constexpr const auto enabler = enable_t::_;
|
constexpr const auto enabler = enable_t::_;
|
||||||
|
|
||||||
|
template<bool value, typename T = void>
|
||||||
|
using disable_if_t = std::enable_if_t<!value, T>;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
using enable = std::enable_if_t<all<Args...>::value, enable_t>;
|
using enable = std::enable_if_t<all<Args...>::value, enable_t>;
|
||||||
|
|
||||||
|
|
|
@ -259,6 +259,34 @@ namespace sol {
|
||||||
return closure<Args...>(f, std::forward<Args>(args)...);
|
return closure<Args...>(f, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Sig, typename... Ps>
|
||||||
|
struct function_arguments {
|
||||||
|
std::tuple<Ps...> params;
|
||||||
|
template <typename... Args>
|
||||||
|
function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Sig = function_sig<>, typename... Args>
|
||||||
|
function_arguments<Sig, Args...> as_function(Args&&... args) {
|
||||||
|
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct as_table_t {
|
||||||
|
T source;
|
||||||
|
template <typename... Args>
|
||||||
|
as_table_t(Args&&... args) : source(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
|
operator std::add_lvalue_reference_t<T> () {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
as_table_t<T> as_table(T&& container) {
|
||||||
|
return as_table_t<T>(std::forward<T>(container));
|
||||||
|
}
|
||||||
|
|
||||||
struct this_state {
|
struct this_state {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
operator lua_State* () const {
|
operator lua_State* () const {
|
||||||
|
@ -602,17 +630,6 @@ namespace sol {
|
||||||
template <>
|
template <>
|
||||||
struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {};
|
struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct lua_type_of<T, std::enable_if_t<
|
|
||||||
meta::all<
|
|
||||||
meta::has_begin_end<T>,
|
|
||||||
meta::neg<meta::any<
|
|
||||||
std::is_base_of<reference, T>,
|
|
||||||
std::is_base_of<stack_reference, T>
|
|
||||||
>>
|
|
||||||
>::value
|
|
||||||
>> : std::integral_constant<type, type::table> {};
|
|
||||||
|
|
||||||
template <typename C, C v, template <typename...> class V, typename... Args>
|
template <typename C, C v, template <typename...> class V, typename... Args>
|
||||||
struct accumulate : std::integral_constant<C, v> {};
|
struct accumulate : std::integral_constant<C, v> {};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
#include "usertype_metatable.hpp"
|
#include "usertype_metatable.hpp"
|
||||||
#include "simple_usertype_metatable.hpp"
|
#include "simple_usertype_metatable.hpp"
|
||||||
|
#include "container_usertype_metatable.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
247
test_containers.cpp
Normal file
247
test_containers.cpp
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
std::vector<int> test_table_return_one() {
|
||||||
|
return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, int>> test_table_return_two() {
|
||||||
|
return{ { "one", 1 },{ "two", 2 },{ "three", 3 } };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::string> test_table_return_three() {
|
||||||
|
return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
|
||||||
|
sol::state lua;
|
||||||
|
std::vector<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::vector<int>& {
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
lua.script("x = f()");
|
||||||
|
sol::object x = lua["x"];
|
||||||
|
sol::type xt = x.get_type();
|
||||||
|
REQUIRE(xt == sol::type::userdata);
|
||||||
|
sol::table t = x;
|
||||||
|
bool matching;
|
||||||
|
matching = t[1] == 1;
|
||||||
|
REQUIRE(matching);
|
||||||
|
matching = t[2] == 2;
|
||||||
|
REQUIRE(matching);
|
||||||
|
matching = t[3] == 3;
|
||||||
|
REQUIRE(matching);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/vector_roundtrip", "make sure vectors can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::vector<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::vector<int>& {
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
lua.script("x = f()");
|
||||||
|
std::vector<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/list_roundtrip", "make sure lists can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::list<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::list<int>& {
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
lua.script("x = f()");
|
||||||
|
std::list <int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/map_roundtrip", "make sure maps can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
|
||||||
|
lua.set_function("f", [&]() -> std::map<std::string, int>& {
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
lua.script("x = f()");
|
||||||
|
std::map<std::string, int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/unordered_map_roundtrip", "make sure unordered_maps can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
|
||||||
|
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
lua.script("x = f()");
|
||||||
|
std::unordered_map<std::string, int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/custom-usertype", "make sure container usertype metatables can be overridden") {
|
||||||
|
typedef std::unordered_map<int, int> bark;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.new_usertype<bark>("bark",
|
||||||
|
"something", [](const bark& b) {
|
||||||
|
INFO("It works: " << b.at(24));
|
||||||
|
},
|
||||||
|
"size", &bark::size,
|
||||||
|
"at", sol::resolve<const int&>(&bark::at),
|
||||||
|
"clear", &bark::clear
|
||||||
|
);
|
||||||
|
bark obj{ { 24, 50 } };
|
||||||
|
lua.set("a", &obj);
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("a:something()"));
|
||||||
|
lua.set("a", obj);
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("a:something()"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/const-serialization-kvp", "make sure const keys / values are respected") {
|
||||||
|
typedef std::map<int, const int> bark;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
bark obj{ { 24, 50 } };
|
||||||
|
lua.set("a", &obj);
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)"));
|
||||||
|
REQUIRE_THROWS(lua.script("a[24] = 51"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/basic-serialization", "make sure containers are turned into proper userdata and have basic hooks established") {
|
||||||
|
typedef std::vector<int> woof;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 });
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in pairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
|
||||||
|
lua.set("b", w);
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in pairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
lua.set("b", &w);
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in pairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
lua.set("b", std::ref(w));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in pairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // glibc is a fuccboi
|
||||||
|
TEST_CASE("containers/const-serialization", "make sure containers are turned into proper userdata and the basic hooks respect const-ness") {
|
||||||
|
typedef std::vector<const int> woof;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 });
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in pairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
REQUIRE_THROWS(lua.script("b[1] = 20"));
|
||||||
|
}
|
||||||
|
#endif // Fuck you, glibc
|
||||||
|
|
||||||
|
TEST_CASE("containers/table-serialization", "ensure types can be serialized as tables still") {
|
||||||
|
typedef std::vector<int> woof;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in ipairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
|
||||||
|
lua.set("b", sol::as_table(w));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in ipairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
lua.set("b", sol::as_table(&w));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in ipairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
lua.set("b", sol::as_table(std::ref(w)));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.script("for k, v in ipairs(b) do assert(k == v) end");
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/const-correctness", "usertype metatable names should reasonably ignore const attributes") {
|
||||||
|
struct Vec {
|
||||||
|
int x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.new_usertype<Vec>("Vec", "x", &Vec::x, "y", &Vec::y, "z", &Vec::z);
|
||||||
|
|
||||||
|
Vec vec;
|
||||||
|
vec.x = 1;
|
||||||
|
vec.y = 2;
|
||||||
|
vec.z = -3;
|
||||||
|
|
||||||
|
std::vector<Vec> foo;
|
||||||
|
foo.push_back(vec);
|
||||||
|
|
||||||
|
std::vector<Vec const *> bar;
|
||||||
|
bar.push_back(&vec);
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
func = function(vecs)
|
||||||
|
for i, vec in pairs(vecs) do
|
||||||
|
print(i, ":", vec.x, vec.y, vec.z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW({
|
||||||
|
lua["func"](foo);
|
||||||
|
lua["func"](bar);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable from standard containers") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.set_function("test_one", test_table_return_one);
|
||||||
|
lua.set_function("test_two", test_table_return_two);
|
||||||
|
lua.set_function("test_three", test_table_return_three);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(lua.script("a = test_one()"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("b = test_two()"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("c = test_three()"));
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')"));
|
||||||
|
|
||||||
|
sol::table a = lua.get<sol::table>("a");
|
||||||
|
sol::table b = lua.get<sol::table>("b");
|
||||||
|
sol::table c = lua.get<sol::table>("c");
|
||||||
|
|
||||||
|
REQUIRE(a.size() == 10ULL);
|
||||||
|
REQUIRE(a.get<int>(3) == 3);
|
||||||
|
REQUIRE(b.get<int>("one") == 1);
|
||||||
|
REQUIRE(b.get<int>("three") == 3);
|
||||||
|
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
||||||
|
REQUIRE(c.get<std::string>("project") == "sol");
|
||||||
|
}
|
|
@ -3,6 +3,9 @@
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct two_things {
|
struct two_things {
|
||||||
int a;
|
int a;
|
||||||
bool b;
|
bool b;
|
||||||
|
|
117
test_tables.cpp
117
test_tables.cpp
|
@ -2,14 +2,12 @@
|
||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "test_stack_guard.hpp"
|
#include "test_stack_guard.hpp"
|
||||||
|
|
||||||
std::string free_function() {
|
std::string free_function() {
|
||||||
|
@ -17,18 +15,6 @@ std::string free_function() {
|
||||||
return "test";
|
return "test";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> test_table_return_one() {
|
|
||||||
return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, int>> test_table_return_two() {
|
|
||||||
return{ { "one", 1 },{ "two", 2 },{ "three", 3 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, std::string> test_table_return_three() {
|
|
||||||
return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } };
|
|
||||||
}
|
|
||||||
|
|
||||||
struct object {
|
struct object {
|
||||||
std::string operator() () {
|
std::string operator() () {
|
||||||
INFO("member_test()");
|
INFO("member_test()");
|
||||||
|
@ -289,37 +275,6 @@ TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a
|
||||||
REQUIRE(iterations == tablesize);
|
REQUIRE(iterations == tablesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("tables/arbitrary-creation", "tables should be created from standard containers") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.set_function("test_one", test_table_return_one);
|
|
||||||
lua.set_function("test_two", test_table_return_two);
|
|
||||||
lua.set_function("test_three", test_table_return_three);
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.script("a = test_one()"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("b = test_two()"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("c = test_three()"));
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')"));
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')"));
|
|
||||||
|
|
||||||
auto&& a = lua.get<sol::table>("a");
|
|
||||||
auto&& b = lua.get<sol::table>("b");
|
|
||||||
auto&& c = lua.get<sol::table>("c");
|
|
||||||
|
|
||||||
REQUIRE(a.size() == 10ULL);
|
|
||||||
REQUIRE(a.get<int>(3) == 3);
|
|
||||||
REQUIRE(b.get<int>("one") == 1);
|
|
||||||
REQUIRE(b.get<int>("three") == 3);
|
|
||||||
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
|
||||||
REQUIRE(c.get<std::string>("project") == "sol");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("tables/variables", "Check if tables and variables work as intended") {
|
TEST_CASE("tables/variables", "Check if tables and variables work as intended") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::os);
|
lua.open_libraries(sol::lib::base, sol::lib::os);
|
||||||
|
@ -555,71 +510,3 @@ TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") {
|
||||||
REQUIRE(val == bigvec[i]);
|
REQUIRE(val == bigvec[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("tables/returns", "make sure that even references to vectors are being serialized as tables") {
|
|
||||||
sol::state lua;
|
|
||||||
std::vector<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::vector<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
lua.script("x = f()");
|
|
||||||
sol::object x = lua["x"];
|
|
||||||
sol::type xt = x.get_type();
|
|
||||||
REQUIRE(xt == sol::type::table);
|
|
||||||
sol::table t = x;
|
|
||||||
bool matching;
|
|
||||||
matching = t[1] == 1;
|
|
||||||
REQUIRE(matching);
|
|
||||||
matching = t[2] == 2;
|
|
||||||
REQUIRE(matching);
|
|
||||||
matching = t[3] == 3;
|
|
||||||
REQUIRE(matching);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("tables/vector_roundtrip", "make sure vectors can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::vector<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::vector<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
lua.script("x = f()");
|
|
||||||
std::vector<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("tables/list_roundtrip", "make sure lists can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::list<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::list<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
lua.script("x = f()");
|
|
||||||
std::list <int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("tables/map_roundtrip", "make sure maps can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
|
|
||||||
lua.set_function("f", [&]() -> std::map<std::string, int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
lua.script("x = f()");
|
|
||||||
std::map<std::string, int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("tables/unordered_map_roundtrip", "make sure unordered_maps can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
|
|
||||||
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
lua.script("x = f()");
|
|
||||||
std::unordered_map<std::string, int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1203,40 +1203,6 @@ TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/const-correctness", "usertype metatable names should reasonably ignore const attributes") {
|
|
||||||
struct Vec {
|
|
||||||
int x, y, z;
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.new_usertype<Vec>("Vec", "x", &Vec::x, "y", &Vec::y, "z", &Vec::z);
|
|
||||||
|
|
||||||
Vec vec;
|
|
||||||
vec.x = 1;
|
|
||||||
vec.y = 2;
|
|
||||||
vec.z = -3;
|
|
||||||
|
|
||||||
std::vector<Vec> foo;
|
|
||||||
foo.push_back(vec);
|
|
||||||
|
|
||||||
std::vector<Vec const *> bar;
|
|
||||||
bar.push_back(&vec);
|
|
||||||
|
|
||||||
lua.script(R"(
|
|
||||||
func = function(vecs)
|
|
||||||
for i, vec in ipairs(vecs) do
|
|
||||||
print(i, ":", vec.x, vec.y, vec.z)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)");
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW({
|
|
||||||
lua["func"](foo);
|
|
||||||
lua["func"](bar);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
|
TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
|
||||||
static int muh_variable = 25;
|
static int muh_variable = 25;
|
||||||
static int through_variable = 10;
|
static int through_variable = 10;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user