Consider the following example (a simple 2d vector lib). Here there is a single constructor function which returns an object table with methods. My issue with this approach is that it is creating new tables with every constructor. Is there a way to use a single instance of the table but change only the _data field which identifies the point being worked on by the methods? Is this a better approach?
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
const char* test =
"p1 = point(410, 680);"
"p2 = point(320, 120);"
"print('dot='..p1:dot(p2));"
"print('cross='..p1:cross(p2));";
typedef struct point_t {
lua_Number x, y;
} point_t;
point_t* p_new(lua_Number x, lua_Number y) {
point_t* p = malloc(sizeof(point_t));
p->x = x;
p->y = y;
return p;
}
void lua_settabledata(lua_State *L , char * key , void * value) {
lua_pushstring(L, key);
lua_pushlightuserdata(L, value);
lua_settable(L, -3);
}
void lua_settablefunction(lua_State *L, char * key , lua_CFunction value) {
lua_pushstring(L, key);
lua_pushcfunction(L, value);
lua_settable(L, -3);
}
point_t* lua_topoint(lua_State *L, int index) {
point_t* p;
lua_pushstring(L, "_data");
lua_gettable(L, index);
p = lua_touserdata(L, -1);
lua_pop(L, 1);
assert(p);
return p;
}
int l_dot(lua_State *L) {
point_t* p1 = lua_topoint(L, 1);
point_t* p2 = lua_topoint(L, 2);
lua_pushnumber(L, p1->x*p2->x + p1->y*p2->y);
return 1;
}
int l_cross(lua_State *L) {
point_t* p1 = lua_topoint(L, 1);
point_t* p2 = lua_topoint(L, 2);
lua_pushnumber(L, p1->x*p2->y - p1->y*p2->x);
return 1;
}
int l_setx(lua_State *L) {
point_t* p = lua_topoint(L, 1);
p->x = lua_tonumber(L, 2);
return 0;
}
int l_sety(lua_State *L) {
point_t* p = lua_topoint(L, 1);
p->y = lua_tonumber(L, 2);
return 0;
}
int l_getx(lua_State *L) {
point_t* p = lua_topoint(L, 1);
lua_pushnumber(L, p->x);
return 1;
}
int l_gety(lua_State *L) {
point_t* p = lua_topoint(L, 1);
lua_pushnumber(L, p->y);
return 1;
}
int l_point(lua_State* L) {
lua_Number x = lua_tonumber(L, 1);
lua_Number y = lua_tonumber(L, 2);
lua_newtable(L);
lua_settabledata(L , "_data", p_new(x, y));
lua_settablefunction(L , "dot", l_dot);
lua_settablefunction(L , "cross", l_cross);
lua_settablefunction(L , "setx", l_setx);
lua_settablefunction(L , "sety", l_sety);
lua_settablefunction(L , "getx", l_getx);
lua_settablefunction(L , "gety", l_gety);
return 1;
}
int main() {
lua_State* L = lua_open();
luaL_openlibs(L);
lua_register(L, "point", l_point);
if (luaL_loadstring(L, test) || lua_pcall(L, 0, 0, 0))
printf("error: %s", lua_tostring(L, -1));
getchar();
return 0;
}