[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: user data with pointer template
- From: "Panagiotis Vossos" <pavossos@...>
- Date: Fri, 19 Oct 2007 09:40:50 +0300
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;
}