lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

Seems like the gc method isn't registered in the metatable. Are you expecting it to be passed in with the luaL_reg?
Might also want to use your check() function inside your gc() function, since the __gc metamethod itself will be exposed to Lua (yes, this surprised me too):

local a = Udata1.new()
local b = Udata2.new()

local gc = getmetatable(a).__gc
gc(b) -- nasty!


On Oct 16, 2007, at 3:12 PM, Panagiotis Vossos wrote:

I have written the following template to help me when wrapping C/C++
pointers in lua userdata.  Any comments or ideas?

regards,
panagiotis.

/*
  User Data With Pointer AUXiliary template.

  Mostly inspired by `User Data With Pointer Example' on the lua wiki,
  provides definitions for various almost-always-used functions.  The
  second argument is a trait that has only one method `name', that
  returns a string for the wrapped type.  Note that `alloc' does not
  allocate anything (we do not know if the wrapped type has a default
  constructor), just sets up the passed pointer on the lua stack.
 */

#ifndef PAVUDWPAUX_HPP
#define PAVUDWPAUX_HPP

#include <cassert>
#include <string>
#include <cstdio>

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

namespace pav {

    template<typename T, typename Tr>
    struct udwpaux
    {
        typedef T* ptr;
        typedef T** pptr;

        static int setup(lua_State *L, const luaL_reg *m, const luaL_reg *f) {
            const std::string name = Tr::name();
            luaL_newmetatable(L, name.c_str());
            lua_pushstring(L, "__index");
            lua_pushvalue(L, -2);
            lua_settable(L, -3);
            luaL_register(L, NULL, m);
            luaL_register(L, name.c_str(), f);
            return 1;
        }

        static ptr check(lua_State *L, int index) {
            const std::string name = Tr::name();
            luaL_checktype(L, index, LUA_TUSERDATA);
            pptr v = (pptr) luaL_checkudata(L, index, name.c_str());
            if (!v) luaL_typerror(L, index, name.c_str());
            ptr p = *v;
            if (!p) {
                char buf[100];
                std::sprintf(buf, "NULL %s", name.c_str());
                luaL_error(L, buf);
            }
            return p;
        }

        static pptr alloc(lua_State *L, ptr p) {
            const std::string name = Tr::name();
            pptr v = (pptr) lua_newuserdata(L, sizeof(ptr));
            *v = p;
            luaL_getmetatable(L, name.c_str());
            lua_setmetatable(L, -2);
#ifdef SHOWNEWDELETE
            std::printf("NEW %s [%p]\n", name.c_str(), v);
#endif
            return v;
        }

        static int gc(lua_State *L) {
            const std::string name = Tr::name();
            pptr p = (pptr) lua_touserdata(L, 1);
            if (!p) luaL_typerror(L, 1, name.c_str());
            assert(*p);
            delete *p;
#ifdef SHOWNEWDELETE
            std::printf("DELETE %s [%p]!\n", name.c_str(), p);
#endif
            return 0;
        }
    };

}

#endif // PAVUDWPAUX_HPP

grrr waaa
www.grahamwakefield.net