1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-09-30 05:59:07 +00:00

std::function can't be used as a __gc function, provide a simple alternative

This commit is contained in:
Pavel Labath 2010-02-12 15:03:02 +01:00
parent 6e5c781a78
commit 2d4d2ef4c0
2 changed files with 27 additions and 12 deletions

View File

@ -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();

View File

@ -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