#include <memory.h>
#include <malloc.h>

#include <stdio.h>

#undef LUA41
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#pragma comment (lib, "lua.lib" )
#pragma comment (lib, "lualib.lib")

lua_State *L;
int objtag;

int ldo(lua_State *L, const char *fn)
{
    int res;
    int top = lua_gettop(L);
    res = lua_dofile(L,fn);
    lua_settop(L,top);
    return res;
}

int gc(lua_State *L)
{
	char *o = (char *)lua_touserdata(L,1);
	printf ("destroy object %x (%s)\n", o, o);
	return 0;
}

void push(char *obj, int tag)
{
#ifdef LUA41
	lua_newuserdatabox(L,obj);
	lua_settag(L,tag);
#else
	lua_pushusertag(L,obj,tag);
#endif
}

int newobj(lua_State *L)
{
	static int cnt = 0;
    char *obj = malloc(10);
	sprintf(obj,"object %d",++cnt);
	printf("Alloc object '%x' (%s)\n",obj,obj);
	push(obj, objtag);
	return 1;
}

char *testScript = "x = test(); y = test(); x = y;";

int main(int argc, char **argv)
{
	char *obj;

	L = lua_open(0);

#ifdef LUA41
	objtag = lua_newtype(L,"test",LUA_TUSERDATA);
#else
	objtag = lua_newtag(L);
#endif
	lua_register(L, "test", newobj);
	lua_pushcfunction(L,gc); lua_settagmethod(L,objtag,"gc");
	lua_dostring(L,testScript);
	lua_getglobal(L,"x");
	obj = (char*) lua_touserdata(L,1);
	printf("got x=%x (%s)\n", obj,obj);
	push(obj,objtag);	// push onto stack again.
	lua_pop(L,1);		// and remove.
	lua_close(L);
}
