mirror of
https://github.com/Llewellynvdm/conky.git
synced 2025-01-17 12:23:56 +00:00
std::function can't be used as a __gc function, provide a simple alternative
This commit is contained in:
parent
6e5c781a78
commit
2d4d2ef4c0
16
src/luamm.cc
16
src/luamm.cc
@ -31,16 +31,6 @@ namespace lua {
|
|||||||
const char lua_exception_namespace[] = "lua::lua_exception_namespace";
|
const char lua_exception_namespace[] = "lua::lua_exception_namespace";
|
||||||
const char this_cpp_object [] = "lua::this_cpp_object";
|
const char this_cpp_object [] = "lua::this_cpp_object";
|
||||||
|
|
||||||
// destructor for C++ objects stored as lua userdata
|
|
||||||
template<typename T>
|
|
||||||
int destroy_cpp_object(lua_State *l)
|
|
||||||
{
|
|
||||||
T *ptr = static_cast<T *>(lua_touserdata(l, -1));
|
|
||||||
assert(ptr);
|
|
||||||
ptr->~T();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts C++ exceptions to strings, so lua can do something with them
|
// converts C++ exceptions to strings, so lua can do something with them
|
||||||
int exception_to_string(lua_State *l)
|
int exception_to_string(lua_State *l)
|
||||||
{
|
{
|
||||||
@ -247,13 +237,15 @@ namespace lua {
|
|||||||
rawsetfield(-2, "__tostring");
|
rawsetfield(-2, "__tostring");
|
||||||
pushboolean(false);
|
pushboolean(false);
|
||||||
rawsetfield(-2, "__metatable");
|
rawsetfield(-2, "__metatable");
|
||||||
lua_pushcfunction(cobj.get(), &destroy_cpp_object<std::exception_ptr>);
|
pushdestructor<std::exception_ptr>();
|
||||||
rawsetfield(-2, "__gc");
|
rawsetfield(-2, "__gc");
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
// a metatable for C++ functions callable from lua code
|
// a metatable for C++ functions callable from lua code
|
||||||
newmetatable(cpp_function_metatable);
|
newmetatable(cpp_function_metatable);
|
||||||
lua_pushcfunction(cobj.get(), &destroy_cpp_object<cpp_function>);
|
pushboolean(false);
|
||||||
|
rawsetfield(-2, "__metatable");
|
||||||
|
pushdestructor<cpp_function>();
|
||||||
rawsetfield(-2, "__gc");
|
rawsetfield(-2, "__gc");
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
|
23
src/luamm.hh
23
src/luamm.hh
@ -143,6 +143,22 @@ namespace lua {
|
|||||||
class state {
|
class state {
|
||||||
std::shared_ptr<lua_State> cobj;
|
std::shared_ptr<lua_State> cobj;
|
||||||
|
|
||||||
|
// destructor for C++ objects stored as lua userdata
|
||||||
|
template<typename T>
|
||||||
|
static int destroy_cpp_object(lua_State *l)
|
||||||
|
{
|
||||||
|
T *ptr = static_cast<T *>(lua_touserdata(l, -1));
|
||||||
|
assert(ptr);
|
||||||
|
try {
|
||||||
|
// throwing exceptions in destructors is a bad idea
|
||||||
|
// but we catch (and ignore) them, just in case
|
||||||
|
ptr->~T();
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool safe_compare(lua_CFunction trampoline, int index1, int index2);
|
bool safe_compare(lua_CFunction trampoline, int index1, int index2);
|
||||||
public:
|
public:
|
||||||
state();
|
state();
|
||||||
@ -218,6 +234,13 @@ namespace lua {
|
|||||||
int ref(int t) { return luaL_ref(cobj.get(), t); }
|
int ref(int t) { return luaL_ref(cobj.get(), t); }
|
||||||
// len recieves length, if not null. Returned value may contain '\0'
|
// len recieves length, if not null. Returned value may contain '\0'
|
||||||
const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); }
|
const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); }
|
||||||
|
// Don't use pushclosure() to create a __gc function. The problem is that lua calls them
|
||||||
|
// in an unspecified order, and we may end up destroying the object holding the
|
||||||
|
// std::function before we get a chance to call it. This pushes a function that simply
|
||||||
|
// calls ~T when the time comes. Only set it as __gc on userdata of type T.
|
||||||
|
template<typename T>
|
||||||
|
void pushdestructor()
|
||||||
|
{ lua_pushcfunction(cobj.get(), &destroy_cpp_object<T>); }
|
||||||
|
|
||||||
// type c, throw everything but the kitchen sink
|
// type c, throw everything but the kitchen sink
|
||||||
// call() is a protected mode call, we don't allow unprotected calls
|
// call() is a protected mode call, we don't allow unprotected calls
|
||||||
|
Loading…
Reference in New Issue
Block a user