I think I have messed up my stack somewhere. Here's ultimately what's happening.
local tg = require "tgeasy"
local drawBuffer = tg.start();
tg.stop();
print(drawBuffer.pointer, getmetatable(drawBuffer.pointer).__name);
local charInfo = tg.CharInfo:new{char = "u"};
print(drawBuffer.pointer, getmetatable(drawBuffer.pointer).__name);
Output:
userdata: 0x7ff6f62032b0 TG.Buffer
userdata: 0x7ff6f62032b0 TG.CharInfo
There are a few layers to this:
1: The underlying c api bindings (Where I suspect the issue) 2: The "helper" lua script that goes between the raw c bindings and a user of the library ("tgeasy.lua") 3: The actual lua script (as seen above)
You have already seen 3, let's move to 2:
local tg = require "libtg"
local tgeasy = {
lib = tg,
VERSION = tg.VERSION,
BINDING_VERSION = tg.BINDING_VERSION,
stop = tg.TGEnd,
EV_KEY = tg.EVENT_KEY,
EV_MOUSE = tg.EVENT_MOUSE,
EV_RESIZE = tg.EVENT_RESIZE,
BLACK = tg.BLACK,
RED = tg.RED,
GREEN = tg.GREEN,
YELLOW = tg.YELLOW,
BLUE = tg.BLUE,
MAGENTA = tg.MAGENTA,
CYAN = tg.CYAN,
WHITE = tg.WHITE,
color = tg.color
};
Buffer = {}
function Buffer:new(o)
o = o or {};
setmetatable(o, self);
self.__index = self;
if(o.width and o.height) then
o.pointer = tg.bufferCreate(o.width, o.height);
end
return o;
end
function Buffer:getSize()
return tg.bufferGetSize(self.pointer);
end
tgeasy.Buffer = Buffer;
function tgeasy.start()
local context = tg.TG();
return Buffer:new{ pointer = context.drawBuffer};
end
CharInfo = {}
function CharInfo:new(o)
o = o or {};
setmetatable(o, self);
self.__index = self;
if(o.char) then o.pointer = tg.charInfo(o.char) end
return o;
end
tgeasy.CharInfo = CharInfo;
return tgeasy;
And now, for the part where I suspect the issue is, the c code (Section 1): (Please note that calls to the TG Library, such as TG()
are not exposed to Lua whatsoever, and the implementations of these calls are therefore not included)
static int luatg_bufferCreate(lua_State* L){
int width = luaL_checkinteger(L, 1);
int height = luaL_checkinteger(L, 2);
if(width < 0 || height < 0) luaL_error(L, "Invalid buffer dimensions");
TGBuffer *buffer = malloc(sizeof(TGBuffer));
*buffer = TGBufCreate(width, height);
lua_pushlightuserdata(L, buffer);
luaL_getmetatable(L, "TG.Buffer");
lua_setmetatable(L, -2);
return 1;
}
static int luatg_bufferGetSize(lua_State* L){
// TODO: Make this a function where no args = return size, two args = set size
TGBuffer *buffer = (TGBuffer *) luaL_checkudata(L, 1, "TG.Buffer");
lua_pushinteger(L, buffer->size.X);
lua_pushinteger(L, buffer->size.Y);
return 2;
}
static int luatg_charInfo(lua_State* L){
int character = luaL_checkstring(L, 1)[0];
TGCharInfo *charInfo = malloc(sizeof(TGCharInfo));
charInfo->UnicodeChar = character;
charInfo->AsciiChar = character;
lua_pushlightuserdata(L, charInfo);
luaL_getmetatable(L, "TG.CharInfo");
lua_setmetatable(L, -2);
return 1;
}
static int luatg_tg(lua_State* L){
lua_newtable(L); // Create a "context" table
TGContext *context = TG();
lua_pushliteral(L, "context"); // Push the actual context pointer, not that we reallyyyy need it
lua_pushlightuserdata(L, context);
luaL_getmetatable(L, "TG.Context"); // Declare this as a TG.Context Lua type
lua_setmetatable(L, -2);
lua_settable(L, -3);
lua_pushliteral(L, "drawBuffer"); // Push the draw buffer, which we DO need
lua_pushlightuserdata(L, &context->drawBuffer);
luaL_getmetatable(L, "TG.Buffer"); // Declare this as a TG.Buffer Lua type
lua_setmetatable(L, -2);
lua_settable(L, -3);
return 1;
}
static int luatg_end(lua_State* L){
TGEnd();
return 0;
}
static const luaL_Reg libtg[] = {
{"bufferCreate", luatg_bufferCreate},
{"bufferGetSize", luatg_bufferGetSize},
{"charInfo", luatg_charInfo}
{"TG", luatg_tg},
{"TGEnd", luatg_end},
{NULL, NULL}
};
LUALIB_API int luaopen_libtg(lua_State* L){
lua_checkstack(L, 25); // Increase the stack size to at least 25
luaL_newmetatable(L, "TG.Context");
luaL_newmetatable(L, "TG.Buffer");
luaL_newmetatable(L, "TG.Color");
luaL_newmetatable(L, "TG.Attributes");
luaL_newmetatable(L, "TG.CharInfo");
luaL_newlib(L, libtg);
lua_pushstring(L, TG_VERSION);
lua_setfield(L, -2, "VERSION");
lua_pushstring(L, "1.0.0");
lua_setfield(L, -2, "BINDING_VERSION");
lua_pushinteger(L, TG_EVENT_KEY);
lua_setfield(L, -2, "EVENT_KEY");
lua_pushinteger(L, TG_EVENT_MOUSE);
lua_setfield(L, -2, "EVENT_MOUSE");
lua_pushinteger(L, TG_EVENT_RESIZE);
lua_setfield(L, -2, "EVENT_RESIZE");
lua_pushinteger(L, TG_MOUSE_LEFT);
lua_setfield(L, -2, "MOUSE_LEFT");
lua_pushinteger(L, TG_MOUSE_RIGHT);
lua_setfield(L, -2, "MOUSE_RIGHT");
lua_pushinteger(L, TG_MMB);
lua_setfield(L, -2, "MMB");
lua_pushinteger(L, TG_MOUSE_MOVE);
lua_setfield(L, -2, "MOUSE_MOVE");
lua_pushinteger(L, TG_MOUSE_CLICK);
lua_setfield(L, -2, "MOUSE_CLICK");
lua_pushinteger(L, TG_BLACK);
lua_setfield(L, -2, "BLACK");
lua_pushinteger(L, TG_RED);
lua_setfield(L, -2, "RED");
lua_pushinteger(L, TG_GREEN);
lua_setfield(L, -2, "GREEN");
lua_pushinteger(L, TG_YELLOW);
lua_setfield(L, -2, "YELLOW");
lua_pushinteger(L, TG_BLUE);
lua_setfield(L, -2, "BLUE");
lua_pushinteger(L, TG_MAGENTA);
lua_setfield(L, -2, "MAGENTA");
lua_pushinteger(L, TG_CYAN);
lua_setfield(L, -2, "CYAN");
lua_pushinteger(L, TG_WHITE);
lua_setfield(L, -2, "WHITE");
return 1;
}