mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Okay, cleaned up includes and now the newest feature:
STATEFUL FUNCTIONS! Any stateful function now works and is properly cleaned up, thanks to some additional metatables that are associated with the function values. This lays the ground work for class bindings, but that's a far off dream. For now, table retrieval and `operator[]` is what's for dinner.
This commit is contained in:
parent
21142e7e7d
commit
19d01ecd1d
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "functional.hpp"
|
||||
#include "stack.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
|
||||
|
@ -112,13 +113,24 @@ struct static_object_lua_func {
|
|||
|
||||
struct lua_func {
|
||||
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)
|
||||
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);
|
||||
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*) {
|
||||
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);
|
||||
return sizeof...(TRn);
|
||||
}
|
||||
|
||||
~lambda_lua_func() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
return sizeof...(TRn);
|
||||
}
|
||||
|
||||
~explicit_lua_func() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TFx, typename T>
|
||||
|
@ -199,7 +219,7 @@ struct explicit_lua_func<TFx, T, true> : public lua_func {
|
|||
} fx;
|
||||
|
||||
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 {
|
||||
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);
|
||||
return sizeof...(TRn);
|
||||
}
|
||||
|
||||
~explicit_lua_func() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
} // sol
|
||||
|
|
|
@ -165,6 +165,17 @@ inline void push(lua_State* L, const std::string& str) {
|
|||
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>
|
||||
inline void push(lua_State* L, const std::array<T, N>& data) {
|
||||
for (auto&& i : data) {
|
||||
|
|
|
@ -24,9 +24,7 @@
|
|||
|
||||
#include "stack.hpp"
|
||||
#include "lua_function.hpp"
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
namespace sol {
|
||||
|
@ -122,7 +120,7 @@ private:
|
|||
template<typename T, typename TFx, typename TObj>
|
||||
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;
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -173,7 +171,7 @@ private:
|
|||
const char* freefuncname = fkey.c_str();
|
||||
const luaL_Reg funcreg[ 2 ] = {
|
||||
{ freefuncname, freefunc },
|
||||
{ nullptr, nullptr }
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
push();
|
||||
|
@ -188,33 +186,31 @@ private:
|
|||
template<typename T>
|
||||
table& set_fx(T&& key, std::unique_ptr<lua_func> luafunc) {
|
||||
std::string fkey(key);
|
||||
|
||||
lua_func* target = luafunc.release();
|
||||
std::string metakey("sol.stateful.");
|
||||
metakey += fkey;
|
||||
metakey += ".meta";
|
||||
lua_func* target = luafunc.release();
|
||||
void* userdata = reinterpret_cast<void*>(target);
|
||||
lua_CFunction freefunc = &lua_func::call;
|
||||
const char* freefuncname = fkey.c_str();
|
||||
const char* metatablename = metakey.c_str();
|
||||
const luaL_Reg funcreg[2] = {
|
||||
{ freefuncname, freefunc },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
push();
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
// Actual function call we want
|
||||
stack::push( state(), userdata );
|
||||
luaL_setfuncs(state(), funcreg, 1);
|
||||
|
||||
int exists = luaL_newmetatable(state(), metatablename);
|
||||
lua_pushstring(state(), "__gc");
|
||||
lua_pushcclosure(state(), &lua_func::gc, 0);
|
||||
lua_settable(state(), -3);
|
||||
push();
|
||||
|
||||
stack::push_user(state(), userdata, metatablename);
|
||||
luaL_setfuncs(state(), funcreg, 1);
|
||||
|
||||
lua_pop(state(), 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static int destroyfunc( lua_State* L ) {
|
||||
void* userdata = lua_touserdata( L, 1 );
|
||||
lua_func* ptr = static_cast<lua_func*>( userdata );
|
||||
std::default_delete<lua_func> dx{ };
|
||||
dx( ptr );
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user