【问题标题】:Array of c++ objects that Lua can access and call member functionsLua 可以访问和调用成员函数的 c++ 对象数组
【发布时间】:2014-01-18 03:01:05
【问题描述】:

我在这里拉扯我的头发,我可以在 Lua 和 c++ 之间共享一个数组,我什至可以在 Lua 中创建一个对象数组(使用下面的代码)并访问它们的成员函数(例如 obj[10]:setPosition (0,0,0))。我不能做的是将 c++ 对象发送到已经存在的 Lua 并让 Lua 调用它们各自的成员函数。例如:

objects = Scene.getAllObjects()
objects[5]:setPosition(0,0,0)

...不起作用,但是,下面的代码有效

for i=1,10 do
  objects[i] = Object.new("Box")
  objects[i]:setPosition(0,0,0)
end

...调用下面的c++函数

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;
}

所以基本上,如果它是在 Lua 中创建的,那么没有问题,但如果 C++ 中已经存在对象,那么我需要将它放入 Lua 表/数组中,以便 Lua 可以对它们施展魔法

请帮忙

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; 
}

【问题讨论】:

  • 你能解释一下它是如何不起作用的吗?你有错误吗?它会崩溃吗?发生什么了? Scene.getAllObjects 返回什么?您确定它返回的是您的对象表(例如,如果您比较 Scene.getAllObjects 返回的 udata 的元表,它是否与 Object.new "Box" 相同)?
  • 元表如下void registerEditableObject() { luaL_Reg regs[] = { { "new", luaAddNewEditableObject }, { "setPosition", luaSetObjectPosition }, { NULL, NULL } }; luaL_newmetatable(L, "luaL_EditableObject"); luaL_register(L, NULL, regs); lua_pushvalue(L, -1); lua_setfield(L, -1, "__index"); lua_setglobal(L, "Object"); }
  • getAllObjects() 应该返回一个表/数组,其中包含 Object.new("Box") 返回的内容,但已经存在的对象。但我不知道该怎么做。提前致谢
  • 为了进一步澄清,Object.new("Box") 返回单个对象的元表,但我需要 getAllObjects() 是对象元表的元表......如果这有意义的话
  • 您能否将Scene.getAllobjects 的C++ sn-p 添加到您的问题中?

标签: c++ lua


【解决方案1】:

好的,我想通了,如果其他人遇到这个问题,我会回答我自己的问题

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;
}

“hello.lua”代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多