Die einfache Version ist, dass ich erwarte, dass meine __tostring-Methode, die ich in C gebaut habe, "glxy_object(100)" ausgibt, wenn ich das Objekt in Lua drucke. Dies geschieht perfekt, wenn ich den Code zwischen den "Problemcode"-Kommentaren auskommentiere (die Bits, die die Tabellendaten von der new()-Methode einlesen). Offensichtlich bringe ich den Stack nicht dorthin zurück, wo er hingehört, aber ich habe zu lange auf diesen Code gestarrt, um zu erkennen, wo der Fehler liegt.
main.c
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
typedef struct {
double x;
double y;
double z;
} glxy_vector3;
typedef struct {
int id;
glxy_vector3 position;
glxy_vector3 rotation;
} glxy_object;
#define OBJNAME "glxy_object"
static int glxy_object_new(lua_State *L) {
int n = lua_gettop(L);
if (n != 2)
return luaL_error(L, "Got %d arguments expected 2", n);
size_t nbytes = sizeof(glxy_object);
glxy_object *o = (glxy_object *)lua_newuserdata(L, nbytes);
luaL_getmetatable(L, OBJNAME);
lua_setmetatable(L, -2);
// id
o->id = luaL_checknumber(L, 1);
// TROUBLE CODE
lua_pop(L, 1);
lua_pushstring(L, "position");
lua_gettable(L, -2);
lua_getfield(L, -1, "x");
o->position.x = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "y");
o->position.y = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "z");
o->position.z = lua_tonumber(L, -1);
lua_pop(L, 2);
lua_pushstring(L, "rotation");
lua_gettable(L, -2);
lua_getfield(L, -1, "x");
o->rotation.x = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "y");
o->rotation.y = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "z");
o->rotation.z = lua_tonumber(L, -1);
lua_pop(L, 2);
// END TROUBLE CODE
// This actually prints the data just fine, so I am reading it correctly at least...
printf("new() - id: %d - position: (%0.2f, %0.2f, %0.2f), rotation: (%0.2f, %0.2f, %0.2f)\n",
o->id, o->position.x, o->position.y, o->position.z, o->rotation.x, o->rotation.y, o->rotation.z
);
return 1;
}
static glxy_object *glxy_object_check(lua_State *L) {
luaL_checktype(L, 1, LUA_TUSERDATA);
glxy_object *o = (glxy_object *)luaL_checkudata(L, 1, OBJNAME);
if (o == NULL) luaL_typerror(L, 1, OBJNAME);
return o;
}
static int glxy_object_tostring(lua_State *L) {
glxy_object *o = (glxy_object *)lua_touserdata(L, 1);
if (o == NULL) luaL_typerror(L, 1, OBJNAME);
lua_pushfstring(L, "glxy_object(%d)", o->id);
return 1;
}
static const struct luaL_reg glxy_object_f[] = {
{ "new", glxy_object_new },
{ NULL, NULL }
};
static const struct luaL_reg glxy_object_m[] = {
{ "__tostring", glxy_object_tostring },
{ NULL, NULL }
};
int glxy_register_object(lua_State *L) {
luaL_openlib(L, OBJNAME, glxy_object_f, 0);
luaL_newmetatable(L, OBJNAME);
luaL_openlib(L, 0, glxy_object_m, 0);
lua_pushliteral(L, "__index");
lua_pushvalue(L, -3);
lua_rawset(L, -3);
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, -3);
lua_rawset(L, -3);
lua_pop(L, 1);
return 1;
}
int main(void) {
// setup lua
L = luaL_newstate();
luaL_openlibs(L);
// register Lua accessable C objects
glxy_register_object(L);
lua_pop(L, 1);
luaL_dofile(L, "main.lua");
return 0;
}
main.lua
local o = glxy_object.new(100, { position={ x=1.0, y=2.0, z=3.0 }, rotation={ x=4.0, y=5.0, z=6.0 } })
print(o)
Stromausgabe
new() - id: 100 - position: (1.00, 2.00, 3.00), rotation: (4.00, 5.00, 6.00)
table: 0x7fe702510b70
erwartete Ausgabe / Ausgabe beim Auskommentieren von 'trouble code' (abzüglich falscher pos/rot-Werte)
new() - id: 100 - position: (0.00, 0.00, 0.00), rotation: (0.00, 0.00, 0.00)
glxy_object(100)
Ich habe meine Code-Basis auf Lesbarkeit getrimmt/zusammengefasst.