mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fix for Issue #35
Userdata now properly forwards arguments to constructor get_call now properly has extra parameters to allow for forwarding items from the first call that are not popped Added tests to cover new cases
This commit is contained in:
parent
05dcba2fac
commit
d35de4a8fa
3
.gitignore
vendored
3
.gitignore
vendored
@ -25,3 +25,6 @@ lib/liblua5.2.a
|
||||
*.includes
|
||||
*.pyc
|
||||
main.cpp
|
||||
lua-5.2.3/
|
||||
build.ninja
|
||||
main.ninja
|
||||
|
40
sol/default_construct.hpp
Normal file
40
sol/default_construct.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013 Danny Y., Rapptz
|
||||
|
||||
// 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_DEFAULT_CONSTRUCTOR_HPP
|
||||
#define SOL_DEFAULT_CONSTRUCTOR_HPP
|
||||
|
||||
#include <memory>
|
||||
#include "traits.hpp"
|
||||
|
||||
namespace sol {
|
||||
|
||||
struct default_construct {
|
||||
template <typename T, typename... Args>
|
||||
void operator()(T&& obj, Args&&... args) const {
|
||||
std::allocator<Unqualified<T>> alloc{};
|
||||
alloc.construct(obj, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // sol
|
||||
|
||||
#endif // SOL_DEFAULT_CONSTRUCTOR_HPP
|
@ -220,7 +220,7 @@ struct pusher {
|
||||
|
||||
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||
static void push(lua_State* L, T&& t) {
|
||||
detail::push_userdata<U>(L, userdata_traits<T*>::metatable, std::move(t));
|
||||
detail::push_userdata<U>(L, userdata_traits<T>::metatable, std::move(t));
|
||||
}
|
||||
};
|
||||
|
||||
@ -378,8 +378,8 @@ inline auto ltr_get(lua_State*, int, F&& f, types<Args...>, types<>, Vs&&... vs)
|
||||
return f(std::forward<Vs>(vs)...);
|
||||
}
|
||||
template<typename F, typename Head, typename... Tail, typename... Vs, typename... Args>
|
||||
inline auto ltr_get(lua_State* L, int index, F&& f, types<Args...> t, types<Head, Tail...>, Vs&&... vs) -> decltype(f(std::declval<Args>()...)) {
|
||||
return ltr_get(L, index + 1, std::forward<F>(f), t, types<Tail...>(), std::forward<Vs>(vs)..., stack::get<Head>(L, index));
|
||||
inline auto ltr_get(lua_State* L, int index, F&& f, types<Args...>, types<Head, Tail...>, Vs&&... vs) -> decltype(f(std::declval<Args>()...)) {
|
||||
return ltr_get(L, index + 1, std::forward<F>(f), types<Args...>(), types<Tail...>(), std::forward<Vs>(vs)..., stack::get<Head>(L, index));
|
||||
}
|
||||
|
||||
template<typename F, typename... Vs, typename... Args>
|
||||
@ -427,14 +427,14 @@ inline void push_reverse(lua_State* L, std::tuple<Args...>&& tuplen) {
|
||||
detail::push_tuple(L, build_reverse_indices<sizeof...(Args)>(), std::move(tuplen));
|
||||
}
|
||||
|
||||
template<typename... Args, typename TFx>
|
||||
inline auto get_call(lua_State* L, int index, TFx&& fx, types<Args...> t) -> decltype(detail::ltr_get(L, index, std::forward<TFx>(fx), t, t)) {
|
||||
return detail::ltr_get(L, index, std::forward<TFx>(fx), t, t);
|
||||
template<typename... Args, typename TFx, typename... Vs>
|
||||
inline auto get_call(lua_State* L, int index, TFx&& fx, types<Args...> t, Vs&&... vs) -> decltype(detail::ltr_get(L, index, std::forward<TFx>(fx), t, t, std::forward<Vs>(vs)...)) {
|
||||
return detail::ltr_get(L, index, std::forward<TFx>(fx), t, t, std::forward<Vs>(vs)...);
|
||||
}
|
||||
|
||||
template<typename... Args, typename TFx>
|
||||
inline auto get_call(lua_State* L, TFx&& fx, types<Args...> t) -> decltype(get_call(L, 1, std::forward<TFx>(fx), t)) {
|
||||
return get_call(L, 1, std::forward<TFx>(fx), t);
|
||||
template<typename TFx, typename... Args, typename... Vs>
|
||||
inline auto get_call(lua_State* L, TFx&& fx, types<Args...> t, Vs&&... vs) -> decltype(get_call(L, 1, std::forward<TFx>(fx), t, std::forward<Vs>(vs)...)) {
|
||||
return get_call(L, 1, std::forward<TFx>(fx), t, std::forward<Vs>(vs)...);
|
||||
}
|
||||
|
||||
template<typename... Args, typename TFx>
|
||||
|
@ -26,6 +26,9 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace sol {
|
||||
template <typename T>
|
||||
struct identity { typedef T type; };
|
||||
|
||||
template<class T, class...>
|
||||
struct are_same : std::true_type { };
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "state.hpp"
|
||||
#include "function_types.hpp"
|
||||
#include "userdata_traits.hpp"
|
||||
#include "default_construct.hpp"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
@ -56,11 +57,8 @@ private:
|
||||
struct constructor {
|
||||
template<typename... Args>
|
||||
static void do_constructor(lua_State* L, T* obj, call_syntax syntax, int, types<Args...>) {
|
||||
auto fx = [&obj] (Args&&... args) -> void {
|
||||
std::allocator<T> alloc{};
|
||||
alloc.construct(obj, std::forward<Args>(args)...);
|
||||
};
|
||||
stack::get_call(L, 1 + static_cast<int>(syntax), fx, types<Args...>());
|
||||
default_construct fx{};
|
||||
stack::get_call(L, 1 + static_cast<int>(syntax), fx, types<Args...>(), obj);
|
||||
}
|
||||
|
||||
static void match_constructor(lua_State*, T*, call_syntax, int) {
|
||||
@ -83,7 +81,7 @@ private:
|
||||
|
||||
void* udata = lua_newuserdata(L, sizeof(T));
|
||||
T* obj = static_cast<T*>(udata);
|
||||
match_constructor(L, obj, syntax, argcount - static_cast<int>(syntax), typename std::common_type<TTypes>::type()...);
|
||||
match_constructor(L, obj, syntax, argcount - static_cast<int>(syntax), typename identity<TTypes>::type()...);
|
||||
|
||||
|
||||
if (luaL_newmetatable(L, std::addressof(meta[0])) == 1) {
|
||||
|
51
tests.cpp
51
tests.cpp
@ -636,10 +636,14 @@ TEST_CASE("tables/issue-number-twenty-five", "Using pointers and references from
|
||||
return x;
|
||||
}
|
||||
|
||||
test* clone() {
|
||||
test* pget() {
|
||||
return this;
|
||||
}
|
||||
|
||||
test create_get() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
int fun(int x) {
|
||||
return x * 10;
|
||||
}
|
||||
@ -647,10 +651,10 @@ TEST_CASE("tables/issue-number-twenty-five", "Using pointers and references from
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
lua.new_userdata<test>("test", "set", &test::set, "get", &test::get, "clone", &test::clone, "fun", &test::fun);
|
||||
lua.new_userdata<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
|
||||
REQUIRE_NOTHROW(lua.script("x = test.new()\n"
|
||||
"x:set():get()"));
|
||||
REQUIRE_NOTHROW(lua.script("y = x:clone()"));
|
||||
REQUIRE_NOTHROW(lua.script("y = x:pointer_get()"));
|
||||
REQUIRE_NOTHROW(lua.script("y:set():get()"));
|
||||
REQUIRE_NOTHROW(lua.script("y:fun(10)"));
|
||||
REQUIRE_NOTHROW(lua.script("x:fun(10)"));
|
||||
@ -659,3 +663,44 @@ TEST_CASE("tables/issue-number-twenty-five", "Using pointers and references from
|
||||
REQUIRE_NOTHROW(lua.script("assert(y:set():get() == y:set():get(), '...')"));
|
||||
REQUIRE_NOTHROW(lua.script("assert(y:set():get() == 10, '...')"));
|
||||
}
|
||||
|
||||
TEST_CASE("userdata/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
|
||||
struct Vec {
|
||||
float x, y, z;
|
||||
Vec(float x, float y, float z) : x{x}, y{y}, z{z} {}
|
||||
float length() {
|
||||
return sqrtf(x*x + y*y + z*z);
|
||||
}
|
||||
Vec normalized() {
|
||||
float invS = 1 / length();
|
||||
return {x * invS, y * invS, z * invS};
|
||||
}
|
||||
};
|
||||
|
||||
struct Line {
|
||||
Vec p1, p2;
|
||||
Line() : p1{0, 0, 0}, p2{0, 0, 0} {}
|
||||
Line(float x) : p1{x, x, x}, p2{x, x, x} {}
|
||||
Line(const Vec& p1) : p1{p1}, p2{p1} {}
|
||||
Line(Vec p1, Vec p2) : p1{p1}, p2{p2} {}
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
sol::constructors<sol::types<>, sol::types<Vec>, sol::types<Vec, Vec>> lctor;
|
||||
sol::userdata<Line> ludata("Line", lctor);
|
||||
lua.set_userdata(ludata);
|
||||
|
||||
sol::constructors<sol::types<float, float, float>> ctor;
|
||||
sol::userdata<Vec> udata("Vec", ctor,
|
||||
"normalized", &Vec::normalized,
|
||||
"length", &Vec::length);
|
||||
|
||||
lua.set_userdata(udata);
|
||||
|
||||
REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
|
||||
"print(v:length())"));
|
||||
REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
|
||||
"print(v:normalized():length())" ));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user