在SWIG调用中返回一个Lua表格

我有一个叫 GetEnemiesLua 的方法的类。我使用 SWIG 将该类绑定到 lua,可以使用我的 lua 代码调用此方法。

我正在尝试让该方法返回对象的 lua 表。

这是我的当前代码:

void CGame::GetEnemiesLua(){
 std::vector<Unit*> enemies = callback->GetEnemyUnits();
 if( enemies.empty()){
  lua_pushnil(ai->L);
  return;
 } else{
  lua_newtable(ai->L);
  int top = lua_gettop(ai->L);
  int index = 1;

  for (std::vector<Unit*>::iterator it = enemies.begin(); it != enemies.end(); ++it) {

   //key
   lua_pushinteger(ai->L,index);//lua_pushstring(L, key);

   //value
   CUnit* unit = new CUnit(callback,*it,this);
   ai->PushIUnit(unit);
   lua_settable(ai->L, -3);
   ++index;
  }
  ::lua_pushvalue(ai->L,-1);
 }
}

PushIUnit 的代码如下:

void CTestAI::PushIUnit(IUnit* unit){
 SWIG_NewPointerObj(L,unit,SWIGTYPE_p_IUnit,1);
}

我用以下代码来测试:

 t = game:GetEnemiesLua()
 if t == nil then
  game:SendToConsole("t is nil! ")
 end

结果总是“t is nil”,尽管这是不正确的。我在代码中设了断点,它确实在循环中,而不是执行“lua_pushnil”。

那么我该如何使我的方法在通过 lua 调用时返回表格呢?

原文链接 https://stackoverflow.com/questions/2751084

点赞
stackoverflow用户41661
stackoverflow用户41661

上帝只知道 SWIG 在做什么(Lua API 是如此简单,以至于我避免使用 SWIG 及其小伙伴),但在某个地方,您需要向 Lua 通信,表明您不仅要将表留在堆栈顶部,还要 返回 该表。如果您自己编写 C 代码,则return 1;可以做到。我不知道如何说服 SWIG 为您返回一个值,但我敢打赌,void返回类型对您不会有任何好处。

您可以尝试绕开 SWIG,只需创建函数原型为

int lua_get_enemies(lua_State *L);

如果您可以使内部工作正常,仅使用 return 1; 和堆栈顶部的表来结束程序可能就可以实现。

2010-05-01 18:43:55
stackoverflow用户48940
stackoverflow用户48940

你的 GetEnemies 函数返回 void,这会被 SWIG 直接理解为忽略任何你试图返回的值。你需要指定你的 C 函数要么返回一个数组,要么获取一个指向数组的指针。

例如,

std::vector<Unit*>& CGame::GetEnemiesLua()
{
    return callback->GetEnemyUnits();
}

接下来,告诉 SWIG 如何解释这个输出值:

// 将返回值转换为 Lua 表格
%typemap(argout, noblock=1) std::vector<Unit*>&
{
     SWIG_arg += ConvertEnemyVectorToLuaTable(*$1);
}

你的转换函数应该返回 '1',表示你已经将一个表格推入了堆栈中。

int ConvertEnenyVectorToLuaTable(std::vector<Unit*>& enemies)
{
    if(enemies->empty())
    {
        lua_pushnil(ai->L);
        return 1;  // 你确实推入了 NIL 值
    }
    else
    {
        lua_newtable(ai->L);
        int top = lua_gettop(ai->L);
        int index = 1;

        for (std::vector<Unit*>::iterator it = enemies.begin();
             it != enemies.end();
             ++it)
        {
            //key
            lua_pushinteger(ai->L,index);

            //value
            ai->PushIUnit(*it);

            // 设置表项
            lua_settable(ai->L, -3);

            ++index;
         }

        // 推入新表
        ::lua_pushvalue(ai->L,-1);
        return 1;
    }
}
2010-05-06 14:14:53