Merge branch 'master' of https://github.com/ThePhD/sol into ThePhD

This commit is contained in:
Rapptz 2013-12-09 14:27:39 -05:00
commit 404dc641a9
3 changed files with 60 additions and 29 deletions

View File

@ -24,6 +24,7 @@
#include "functional.hpp" #include "functional.hpp"
#include "stack.hpp" #include "stack.hpp"
#include <memory>
namespace sol { namespace sol {
@ -112,14 +113,25 @@ struct static_object_lua_func {
struct lua_func { struct lua_func {
static int call(lua_State* L) { static int call(lua_State* L) {
void* inheritancedata = lua_touserdata(L, lua_upvalueindex(1)); void** pinheritancedata = static_cast<void**>(lua_touserdata(L, lua_upvalueindex(1)));
void* inheritancedata = *pinheritancedata;
if (inheritancedata == nullptr) if (inheritancedata == nullptr)
throw sol_error("call from lua to c++ function has null data"); throw sol_error("call from lua to c++ function has null data");
lua_func& fx = *static_cast<lua_func*>(inheritancedata); lua_func* pfx = static_cast<lua_func*>(inheritancedata);
lua_func& fx = *pfx;
int r = fx(L); int r = fx(L);
return r; return r;
} }
static int gc(lua_State* L) {
void** puserdata = static_cast<void**>(lua_touserdata(L, 1));
void* userdata = *puserdata;
lua_func* ptr = static_cast<lua_func*>(userdata);
std::default_delete<lua_func> dx{ };
dx(ptr);
return 0;
}
virtual int operator()(lua_State*) { virtual int operator()(lua_State*) {
throw sol_error("Failure to call specialized wrapped C++ function from lua"); throw sol_error("Failure to call specialized wrapped C++ function from lua");
} }
@ -152,6 +164,10 @@ struct lambda_lua_func : public lua_func {
stack::push(L, r); stack::push(L, r);
return sizeof...(TRn); return sizeof...(TRn);
} }
~lambda_lua_func() {
}
}; };
template<typename TFx, typename T = TFx, bool is_member_pointer = std::is_member_function_pointer<TFx>::value> template<typename TFx, typename T = TFx, bool is_member_pointer = std::is_member_function_pointer<TFx>::value>
@ -179,6 +195,10 @@ struct explicit_lua_func : public lua_func {
stack::push(L, std::move(r)); stack::push(L, std::move(r));
return sizeof...(TRn); return sizeof...(TRn);
} }
~explicit_lua_func() {
}
}; };
template<typename TFx, typename T> template<typename TFx, typename T>
@ -199,7 +219,7 @@ struct explicit_lua_func<TFx, T, true> : public lua_func {
} fx; } fx;
template<typename... FxArgs> template<typename... FxArgs>
explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move( m ), std::forward<FxArgs>(fxargs)...) {} explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward<FxArgs>(fxargs)...) {}
virtual int operator()(lua_State* L) override { virtual int operator()(lua_State* L) override {
return (*this)(tuple_types<typename fx_traits::return_type>(), typename fx_traits::args_type(), L); return (*this)(tuple_types<typename fx_traits::return_type>(), typename fx_traits::args_type(), L);
@ -217,6 +237,10 @@ struct explicit_lua_func<TFx, T, true> : public lua_func {
stack::push(L, r); stack::push(L, r);
return sizeof...(TRn); return sizeof...(TRn);
} }
~explicit_lua_func() {
}
}; };
} // sol } // sol

View File

@ -165,6 +165,17 @@ inline void push(lua_State* L, const std::string& str) {
lua_pushlstring(L, str.c_str(), str.size()); lua_pushlstring(L, str.c_str(), str.size());
} }
template<typename T>
inline void push_user(lua_State* L, T& userdata, const char* metatablekey) {
T* pdatum = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
T& datum = *pdatum;
datum = userdata;
if (metatablekey != nullptr) {
lua_getfield(L, LUA_REGISTRYINDEX, metatablekey);
lua_setmetatable(L, -2);
}
}
template<typename T, size_t N> template<typename T, size_t N>
inline void push(lua_State* L, const std::array<T, N>& data) { inline void push(lua_State* L, const std::array<T, N>& data) {
for (auto&& i : data) { for (auto&& i : data) {

View File

@ -24,9 +24,7 @@
#include "stack.hpp" #include "stack.hpp"
#include "lua_function.hpp" #include "lua_function.hpp"
#include <unordered_map>
#include <array> #include <array>
#include <memory>
#include <cstring> #include <cstring>
namespace sol { namespace sol {
@ -42,11 +40,9 @@ namespace detail {
} }
} }
class table : virtual public reference { class table : virtual public reference {
private:
std::unordered_map<std::string, std::shared_ptr<lua_func>> funcs;
public: public:
table() noexcept: reference(), funcs() {} table() noexcept: reference() {}
table(lua_State* L, int index = -1): reference(L, index), funcs() { table(lua_State* L, int index = -1): reference(L, index) {
type_assert(L, index, type::table); type_assert(L, index, type::table);
} }
@ -98,7 +94,7 @@ private:
table& set_isfunction_fx(std::false_type, T&& key, TFx&& fx) { table& set_isfunction_fx(std::false_type, T&& key, TFx&& fx) {
typedef typename std::decay<TFx>::type clean_lambda; typedef typename std::decay<TFx>::type clean_lambda;
typedef typename detail::function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t; typedef typename detail::function_traits<decltype(&clean_lambda::operator())>::free_function_pointer_type raw_func_t;
typedef std::is_convertible<clean_lambda, raw_func_t> isconvertible; typedef std::is_convertible<clean_lambda, raw_func_t> isconvertible;
return set_isconvertible_fx(isconvertible(), std::forward<T>(key), std::forward<TFx>(fx)); return set_isconvertible_fx(isconvertible(), std::forward<T>(key), std::forward<TFx>(fx));
} }
@ -124,7 +120,7 @@ private:
template<typename T, typename TFx, typename TObj> template<typename T, typename TFx, typename TObj>
table& set_lvalue_fx(std::false_type, T&& key, TFx&& fx, TObj&& obj) { table& set_lvalue_fx(std::false_type, T&& key, TFx&& fx, TObj&& obj) {
typedef typename std::remove_pointer<typename std::decay<TFx>::type>::type clean_fx; typedef typename std::remove_pointer<typename std::decay<TFx>::type>::type clean_fx;
std::unique_ptr<lua_func> sptr(new explicit_lua_func<clean_fx, TObj>(std::forward<TObj>( obj ), std::forward<TFx>(fx))); std::unique_ptr<lua_func> sptr(new explicit_lua_func<clean_fx, TObj>(std::forward<TObj>(obj), std::forward<TFx>(fx)));
return set_fx(std::forward<T>(key), std::move(sptr)); return set_fx(std::forward<T>(key), std::move(sptr));
} }
@ -175,7 +171,7 @@ private:
const char* freefuncname = fkey.c_str(); const char* freefuncname = fkey.c_str();
const luaL_Reg funcreg[ 2 ] = { const luaL_Reg funcreg[ 2 ] = {
{ freefuncname, freefunc }, { freefuncname, freefunc },
{ nullptr, nullptr } { nullptr, nullptr }
}; };
push(); push();
@ -190,27 +186,27 @@ private:
template<typename T> template<typename T>
table& set_fx(T&& key, std::unique_ptr<lua_func> luafunc) { table& set_fx(T&& key, std::unique_ptr<lua_func> luafunc) {
std::string fkey(key); std::string fkey(key);
auto hint = funcs.find(fkey); std::string metakey("sol.stateful.");
if (hint == funcs.end()) { metakey += fkey;
std::shared_ptr<lua_func> sptr(luafunc.release()); metakey += ".meta";
hint = funcs.emplace_hint(hint, fkey, std::move(sptr)); lua_func* target = luafunc.release();
}
else {
hint->second.reset(luafunc.release());
}
lua_func* target = hint->second.get();
void* userdata = reinterpret_cast<void*>(target); void* userdata = reinterpret_cast<void*>(target);
lua_CFunction freefunc = &lua_func::call; lua_CFunction freefunc = &lua_func::call;
const char* freefuncname = hint->first.c_str(); const char* freefuncname = fkey.c_str();
const luaL_Reg funcreg[ 2 ] = { const char* metatablename = metakey.c_str();
const luaL_Reg funcreg[2] = {
{ freefuncname, freefunc }, { freefuncname, freefunc },
{ nullptr, nullptr } { nullptr, nullptr }
}; };
push(); int exists = luaL_newmetatable(state(), metatablename);
lua_pushstring(state(), "__gc");
lua_pushcclosure(state(), &lua_func::gc, 0);
lua_settable(state(), -3);
push();
stack::push(state(), userdata); stack::push_user(state(), userdata, metatablename);
luaL_setfuncs(state(), funcreg, 1); luaL_setfuncs(state(), funcreg, 1);
lua_pop(state(), 1); lua_pop(state(), 1);
return *this; return *this;