metamethods for containers represented using userdata,

`#` == __len
`[key] = value` == __newindex
`key` == __index
are not working properly for some reason, will need to investigate more deeply to find out why
on bright side all tests pass including new tests added (for take/return std::function)
fixed some things forgot to change with addition of upvalue_t for clarity (see previous commit about userdata/lightuserdata vs upvalue)
This commit is contained in:
PrincessNyanara 2014-06-07 11:00:27 -04:00 committed by Rapptz
parent 3306b44162
commit 6712ebe0bd
4 changed files with 29 additions and 21 deletions

View File

@ -37,8 +37,8 @@ struct container {
namespace stack { namespace stack {
template<typename T> template<typename T>
struct pusher<T, typename std::enable_if<has_begin_end<T>::value>::type> { struct pusher<T, typename std::enable_if<has_begin_end<T>::value>::type> {
template <typename U> template<typename U = T, EnableIf<Not<has_key_value_pair<U>>> = 0>
static void push(lua_State *L, U&& t){ static void push(lua_State* L, const T& cont) {
typedef container<U> container_t; typedef container<U> container_t;
// todo: NEED to find a different way of handling this... // todo: NEED to find a different way of handling this...
static std::vector<std::shared_ptr<void>> classes{}; static std::vector<std::shared_ptr<void>> classes{};
@ -53,27 +53,13 @@ struct pusher<T, typename std::enable_if<has_begin_end<T>::value>::type> {
container_t* c = static_cast<container_t*>(lua_newuserdata(L, sizeof(container_t))); container_t* c = static_cast<container_t*>(lua_newuserdata(L, sizeof(container_t)));
std::allocator<container_t> alloc{}; std::allocator<container_t> alloc{};
alloc.construct(c, std::forward<U>(t)); alloc.construct(c, cont);
auto&& meta = userdata_traits<T>::metatable; auto&& meta = userdata_traits<T>::metatable;
luaL_getmetatable(L, std::addressof(meta[0])); luaL_getmetatable(L, std::addressof(meta[0]));
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
} }
template<typename U = T, EnableIf<Not<has_key_value_pair<U>>> = 0>
static void push(lua_State* L, const T& cont) {
lua_createtable(L, cont.size(), 0);
unsigned index = 1;
for(auto&& i : cont) {
// push the index
pusher<unsigned>::push(L, index++);
// push the value
pusher<Unqualified<decltype(i)>>::push(L, i);
// set the table
lua_settable(L, -3);
}
}
template<typename U = T, EnableIf<has_key_value_pair<U>> = 0> template<typename U = T, EnableIf<has_key_value_pair<U>> = 0>
static void push(lua_State* L, const T& cont) { static void push(lua_State* L, const T& cont) {
lua_createtable(L, cont.size(), 0); lua_createtable(L, cont.size(), 0);

View File

@ -180,7 +180,7 @@ struct base_function {
struct userdata { struct userdata {
static int call(lua_State* L) { static int call(lua_State* L) {
// Zero-based template parameter, but upvalues start at 1 // Zero-based template parameter, but upvalues start at 1
return base_call(L, stack::get<lightuserdata_t>(L, i + 1)); return base_call(L, stack::get<upvalue_t>(L, i + 1));
} }
}; };

View File

@ -286,7 +286,7 @@ template<typename T, typename... Args>
inline void push(lua_State* L, T&& t, Args&&... args) { inline void push(lua_State* L, T&& t, Args&&... args) {
using swallow = char[]; using swallow = char[];
pusher<Unqualified<T>>{}.push(L, std::forward<T>(t)); pusher<Unqualified<T>>{}.push(L, std::forward<T>(t));
void(swallow{'\0', (pusher<Unqualified<T>>{}.push(L, std::forward<Args>(args)), '\0')... }); void(swallow{'\0', (pusher<Unqualified<Args>>{}.push(L, std::forward<Args>(args)), '\0')... });
} }
template<typename T, typename U = Unqualified<T>> template<typename T, typename U = Unqualified<T>>

View File

@ -14,6 +14,18 @@ void test_free_func2(std::function<int(int)> f, int arg1) {
throw sol::error("failed function call!"); throw sol::error("failed function call!");
} }
std::function<int()> makefn () {
auto fx = []() -> int {
return 0x1456789;
};
return fx;
}
void takefn ( std::function<int()> purr ) {
if (purr() != 0x1456789)
throw 0;
}
std::string free_function() { std::string free_function() {
std::cout << "free_function()" << std::endl; std::cout << "free_function()" << std::endl;
return "test"; return "test";
@ -320,7 +332,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work
std::cout << "stateless lambda()" << std::endl; std::cout << "stateless lambda()" << std::endl;
return "test"; return "test";
} }
); );
REQUIRE_NOTHROW(run_script(lua)); REQUIRE_NOTHROW(run_script(lua));
lua.get<sol::table>("os").set_function("fun", &free_function); lua.get<sol::table>("os").set_function("fun", &free_function);
@ -388,6 +400,17 @@ TEST_CASE("functions/sol::function to std::function", "check if conversion to st
); );
} }
TEST_CASE("functions/returning functions from C++ and getting in lua", "check to see if returning a functor and getting a functor from lua is possible") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.set_function( "makefn", makefn );
lua.set_function( "takefn", takefn );
lua.script( "afx = makefn()\n"
"print(afx())\n"
"takefn(afx)\n" );
}
TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
@ -558,7 +581,6 @@ TEST_CASE("tables/userdata utility derived", "userdata classes must play nice wh
REQUIRE((lua.get<int>("dgn") == 7)); REQUIRE((lua.get<int>("dgn") == 7));
} }
TEST_CASE("tables/self-referential userdata", "userdata classes must play nice when C++ object types are requested for C++ code") { TEST_CASE("tables/self-referential userdata", "userdata classes must play nice when C++ object types are requested for C++ code") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);