lua-users home
lua-l archive

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


On 10/17/07, Jose Marin <jose_marin2@yahoo.com.br> wrote:
> Great, but some samples on how to use it properly would be nice! :-)
>

Sure, here is a minimal wrapper for std::vectors.  Note that I don't
bother with multiple instantiations of the template, I just store in
it lua indexes (integers).

#define SHOWNEWDELETE

#include <vector>
#include <string>
#include <iostream>
#include "udwpaux.hpp"

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

namespace {

    struct traitv { static const std::string name() { return "stlvector"; } };
    struct traiti { static const std::string name() { return "stlvectorit"; } };

    typedef std::vector<int> type;
    typedef std::vector<int>::iterator iter;
    typedef pav::udwpaux<type, traitv> helper;
    typedef pav::udwpaux<iter, traiti> helpit;

}

static int
make(lua_State *L)
{
    helper::alloc(L, new type);
    return 1;
}

static int
len(lua_State *L)
{
    const helper::ptr p = helper::check(L, 1);
    lua_pushnumber(L, p->size());
    return 1;
}

static int
push_back(lua_State *L)
{
    helper::ptr p = helper::check(L, 1);
    const int d = luaL_ref(L, LUA_REGISTRYINDEX);
    p->push_back(d);
    return 0;
}

static int
at(lua_State *L)
{
    const helper::ptr p = helper::check(L, 1);
    const int i = luaL_checkint(L, 2);
    const int r = (*p)[i];
    lua_rawgeti(L, LUA_REGISTRYINDEX, r);
    return 1;
}

static int
clear(lua_State *L)
{
    helper::ptr p = helper::check(L, 1);
    p->clear();
    return 0;
}

static int
elems_iter(lua_State *L)
{
    const helpit::ptr itend = helpit::check(L, lua_upvalueindex(1));
    const helpit::ptr it = helpit::check(L, 1);
    const int i = luaL_checkint(L, 2);
    if (*it != *itend) {
        lua_pushnumber(L, i+1);
        lua_rawgeti(L, LUA_REGISTRYINDEX, **it);
        (*it)++;
        return 2;
    } else {
        return 0;
    }
}

static int
elems(lua_State *L)
{
    // push end iterator as upvalue
    {
        helpit::pptr v = helpit::alloc(L, new iter);
        helper::ptr vv = helper::check(L, 1);
        **v = vv->end();
    }

    // push closure
    lua_pushcclosure(L, &elems_iter, 1);

    // push state
    {
        helpit::pptr v = helpit::alloc(L, new iter);
        helper::ptr vv = helper::check(L, 1);
        **v = vv->begin();
    }

    // push var1
    lua_pushnumber(L, -1);
    return 3;
}

static int
gc(lua_State *L)
{
    const std::string name = traitv::name();
    helper::pptr pp = (helper::pptr) lua_touserdata(L, 1);
    if (!pp) luaL_typerror(L, 1, name.c_str());
    assert(*pp);
    helper::ptr p = *pp;
    for (size_t i = 0; i < p->size(); i++)
        luaL_unref(L, LUA_REGISTRYINDEX, (*p)[i]);
    delete p;
#ifdef SHOWNEWDELETE
    std::printf("DELETE %s [%p]!\n", name.c_str(), pp);
#endif
    return 0;
}

static int
reg(lua_State *L)
{
    const luaL_reg funcs[] = {
        { "make", make },
        { 0, 0 }
    };

    const luaL_reg meths[] = {
        { "__gc", gc},
        { "__len", len },
        { "push_back", push_back },
        { "at", at },
        { "clear", clear },
        { "elems", elems },
        {0, 0}
    };

    helper::setup(L, meths, funcs);

    const luaL_reg itfuncs[] = {
        {0, 0}
    };

    const luaL_reg itmeths[] = {
        { "__gc", helpit::gc},
        {0, 0}
    };

    helpit::setup(L, itmeths, itfuncs);

    return 2;
}

extern "C" int
luaopen_stlvector(lua_State *L)
{
    reg(L);
    return 1;
}