如何将一个对象列表从C++传递到Lua?

12
我是Bitfighter的首席开发人员,并正在使用Lua添加用户脚本机器人。我正在使用C++和Lua,使用Lunar将它们粘合在一起。
我试图做一些我认为应该很简单的事情:我在Lua中有一个C++对象(下面的代码中的机器人),并调用其上的一个方法(findItems),该方法使C++搜索机器人周围的区域并返回它找到的对象列表(TestItems和其他未在此处显示的对象)。我的问题只是如何在C++中组装和返回找到的项目列表,然后在Lua中对它们进行迭代?
基本上,我想填写下面的<<<< Create list of items, return it to lua >>>>块,并在Lua代码本身中进行必要的更正,包括在其下方。
我尝试保持代码简单但完整。希望这里没有太多内容!谢谢! C++头文件
class TestItem : public LuaObject
{

public:
   TestItem();     // C++ constructor

   ///// Lua Interface

   TestItem(lua_State *L) { } ;             //  Lua constructor

   static const char className[];
   static Lunar<TestItem>::RegType methods[];

   S32 getClassID(lua_State *L) { return returnInt(L, TestItemType); }
};


class LuaRobot : public Robot
{
   LuaRobot();     // C++ constructor

   ///// Lua Interface

   LuaRobot(lua_State *L) { } ;             //  Lua constructor

   static const char className[];
   static Lunar<LuaRobot>::RegType methods[];

   S32 findItems(lua_State *L);
}

C++ .cpp文件

const char LuaRobot::className[] = "Robot";      // Class name in Lua
// Define the methods we will expose to Lua
Lunar<LuaRobot>::RegType LuaRobot::methods[] =
{
   method(LuaRobot, findItems),
   {0,0}    // End method list
};


S32 LuaRobot::findItems(lua_State *L)
{
   range = getIntFromStack(L, 1);    // Pop range from the stack
   thisRobot->findObjects(fillVector, range);  // Put items in fillVector

   <<<< Create list of items, return it to lua >>>>

   for(int i=0; i < fillVector.size(); i++)
      do something(fillVector[i]);    // Do... what, exactly?

   return something;
}


/////
const char TestItem::className[] = "TestItem";      // Class name in Lua

// Define the methods we will expose to Lua
Lunar<TestItem>::RegType TestItem::methods[] =
{
   // Standard gameItem methods
   method(TestItem, getClassID),
   {0,0}    // End method list
};

Lua 代码

bot = LuaRobot( Robot ) -- This is a reference to our bot

range = 10
items = bot:findItems( range )

for i, v in ipairs( items ) do
    print( "Item Type: " .. v:getClassID() )
end

你正在寻找一种方法来获取Lunar,以创建一个索引从1到fillVector.size()的表格。在纯Lua中,可以通过创建一个表并添加元素来完成。我对Lunar不够了解,无法在该框架中给出具体建议。 - RBerteig
是的,完全正确,这就是我卡住的地方。我可以将多个数字项目添加到表中,但不知道如何添加多个用户数据项目。 - Watusimoto
bot = LuaRobot(Robot) -- 这是对我们机器人的引用 --- 请问,您是如何做到这一点的?您如何获取对于您创建的 C++ 机器人的引用?我尝试创建一个 getCurrent(luastate*) 方法,然后 lunar::push(this),但它没有起作用。我请求您的帮助。 - Icebone1000
2个回答

9

所以你需要填充一个向量并将其推送到Lua。以下是一些示例代码。应用程序是一个std::list

typedef std::list<std::string> Applications;

我创建了一个表格,并用列表中的数据填充它。
int ReturnArray(lua_State* L) {
    lua_createtable(L, applications.size(), 0);
    int newTable = lua_gettop(L);
    int index = 1;
    Applications::const_iterator iter = applications.begin();
    while(iter != applications.end()) {
        lua_pushstring(L, (*iter).c_str());
        lua_rawseti(L, newTable, index);
        ++iter;
        ++index;
    }
    return 1;
}

这让我在堆栈中有了一个数组。如果它被返回给Lua,那么我可以写出以下内容:
for k,v in ipairs( ReturnArray() ) do
    print(v)
end

当然,到目前为止,这只是让我得到了一个Lua字符串数组。要获得一个Lua对象数组,我们需要稍微调整一下您的方法:

S32 LuaRobot::findItems(lua_State *L)
{
    range = getIntFromStack(L, 1);    // Pop range from the stack
    thisRobot->findObjects(fillVector, range);  // Put items in fillVector

    // <<<< Create list of items, return it to lua >>>>

    lua_createtable(L, fillVector.size(), 0);
    int newTable = lua_gettop(L);
    for(int i=0; i < fillVector.size(); i++) {
        TestItem* item = fillVector[i];
        item->push(L);  // put an object, not a string, in Lua array
        lua_rawseti(L, newTable, i + 1);
    }
    return 1;
}

1

这个完美地运作。为了向其他读者澄清,该方法

item->push(L)

void push(lua_State *L) {  Lunar<TestItem>::push(L, this); }

通过将此内容封装在一个方法中,可以使findItems对其查找的内容不加区分。
感谢您的帮助!

1
哇 - 在不同的计算机上,使用相同的用户名可能会成为完全不同的用户!谁知道呢? - Watusimoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接