lua-users home
lua-l archive

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

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


  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.


#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);
            std::printf("NEW %s [%p]\n", name.c_str(), v);
            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());
            delete *p;
            std::printf("DELETE %s [%p]!\n", name.c_str(), p);
            return 0;