mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-18 02:55:12 +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 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
|
||||
int exception_to_string(lua_State *l)
|
||||
{
|
||||
@ -247,13 +237,15 @@ namespace lua {
|
||||
rawsetfield(-2, "__tostring");
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
lua_pushcfunction(cobj.get(), &destroy_cpp_object<std::exception_ptr>);
|
||||
pushdestructor<std::exception_ptr>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
|
||||
// a metatable for C++ functions callable from lua code
|
||||
newmetatable(cpp_function_metatable);
|
||||
lua_pushcfunction(cobj.get(), &destroy_cpp_object<cpp_function>);
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
pushdestructor<cpp_function>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
|
||||
|
23
src/luamm.hh
23
src/luamm.hh
@ -143,6 +143,22 @@ namespace lua {
|
||||
class state {
|
||||
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);
|
||||
public:
|
||||
state();
|
||||
@ -218,6 +234,13 @@ namespace lua {
|
||||
int ref(int t) { return luaL_ref(cobj.get(), t); }
|
||||
// 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); }
|
||||
// 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
|
||||
// call() is a protected mode call, we don't allow unprotected calls
|
||||
|
Loading…
Reference in New Issue
Block a user