Reputation: 51
I am pulling my hair out here, I can share an array between Lua and c++, I can even create an array of objects in Lua (using the code below) and access their member functions (eg obj[10]:setPosition(0,0,0) ). What I can't do is send c++ objects to Lua that already exist and have Lua call their respective member functions. For example:
objects = Scene.getAllObjects()
objects[5]:setPosition(0,0,0)
...doesn't work, however, The code below works
for i=1,10 do
objects[i] = Object.new("Box")
objects[i]:setPosition(0,0,0)
end
...which calls the c++ function below
int luaAddNewEditableObject(lua_State * L)
{
const char * name = luaL_checkstring(L, 1);
EditableObject ** udata = (EditableObject **)lua_newuserdata(L, sizeof(void*));
EditableObject *obj = scene->addNewEditableObject(name);
*udata = obj;
luaL_getmetatable(L, "luaL_EditableObject");
lua_setmetatable(L, -2);
return 1;
}
So basically, if it's created in Lua then no problems, but if there are objects that already exist in c++ then I need to get it into a Lua table/array so Lua can do magic to them
Please Help
struct ObjectArray
{
int size;
EditableObject *objects; /* The cpp objects */
};
static int getAllObjects (lua_State *L)
{
//This creates the metatable for array notation
size_t nbytes = sizeof(ObjectArray) + numObjects * sizeof(ObjectArray*);
ObjectArray *objectArray = (ObjectArray*)lua_newuserdata(L, nbytes);
objectArray->size = numObjects;
for (int i = 0; i < numFoos; i++)
{
//This sets the c++ pointers to the lua_newuserdata
objectArray->objects[i] = objects[i];
//So maybe here I need to assign the 'luaL_EditableObject' metatable for each object
//so I can call it's member functions ??
}
luaL_getmetatable(L, "ObjectArray");
lua_setmetatable(L, -2);
return 1;
}
Upvotes: 1
Views: 898
Reputation: 51
Ok I figured it out and will answer my own question in case anyone else has had this problem
extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <map>
class Object
{
public:
Object()
{
x = 0;
y = 0;
}
Object(int x, int y)
{
this->x = x;
this->y = y;
}
int x, y;
};
std::map<std::string,Object> objects;
static int luaGetObjects(lua_State *L)
{
lua_newtable(L);
int i=0;
for (auto it = objects.begin(); it != objects.end(); it++, i++)
{
lua_pushstring(L, it->first.c_str());
luaL_getmetatable(L, "luaL_Object");
lua_setmetatable(L, -2);
lua_rawseti(L, -2, i+1);
stackDump(L);
}
return 1;
}
static int luaSetPosition(lua_State* L)
{
const char* key = luaL_checkstring(L,1);
int x = luaL_checknumber(L,2);
int y = luaL_checknumber(L,3);
objects[key].x = x;
objects[key].y = y;
return 0;
}
static int luaGetPosition(lua_State* L)
{
const char* key = luaL_checkstring(L,1);
lua_pushnumber(L, objects[key].x);
lua_pushnumber(L, objects[key].y);
return 2;
}
void registerObject(lua_State *L)
{
luaL_Reg regs[] =
{
{ "setPosition", luaSetPosition },
{ "getPosition", luaGetPosition },
{ NULL, NULL }
};
luaL_newmetatable(L, "luaL_Object");
luaL_register(L, NULL, regs);
lua_pushvalue(L, -1);
lua_setfield(L, -1, "__index");
}
int main()
{
lua_State * L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, luaGetObjects);
lua_setglobal(L, "getObjects");
registerObject(L);
objects["id001"] = Object(1,2);
objects["id002"] = Object(3,4);
objects["id003"] = Object(5,6);
int erred = luaL_dofile(L, "hello.lua");
if(erred)
std::cout << "Lua error: " << luaL_checkstring(L, -1) << std::endl;
lua_close(L);
return 0;
}
The 'hello.lua' code:
objects = getObjects()
for i=1,#objects do
x,y = objects[i]:getPosition();
print(string.format("object[%d] x = %d y = %d",i,x,y))
objects[i]:setPosition(x*100, y*100);
x,y = objects[i]:getPosition();
print(string.format("object[%d] x = %d y = %d after mul",i,x,y))
end
Upvotes: 1