lua-users home
lua-l archive

Re: user data with pointer template

[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;
}

AltStyle によって変換されたページ (->オリジナル) /