在SWIG呼叫上返回lua表

时间:2010-05-01 18:28:05

标签: lua swig

我有一个名为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

结果始终不是“零”,尽管这是不正确的。我在代码中放了断点,它确实在循环中,而不是lua_pushnil

那么当通过lua调用时,如何让我的方法返回一个表?

2 个答案:

答案 0 :(得分:1)

上帝只知道SWIG正在做什么(Lua API非常简单以至于我避免了SWIG及其小朋友),但是在某个地方你需要与Lua沟通,你不仅要在堆栈顶部留下一个表,但是你要返回那个表。如果您自己编写C代码return 1;就会这样做。我不知道如何说服SWIG让它为你返回一个值,但我敢打赌,void的返回类型对你没有好处。

您可以尝试使用SWIG,只需使用原型

创建一个函数
int lua_get_enemies(lua_State *L);

如果你可以让内部的东西工作,只需用return 1;结束例程,堆栈顶部的表就可以了。

答案 1 :(得分:1)

你的'GetEnemies'函数返回SWIG字面意义上的void,丢弃你试图返回的任何值。您需要指定C函数以返回数组或将指针指向一个数组。

例如,

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

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

// convert the return value into a Lua table
%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;  // you did push a NIL value
    } 
    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);

            // set the table entry
            lua_settable(ai->L, -3);

            ++index;
         }

        // push the new table
        ::lua_pushvalue(ai->L,-1);
        return 1;
    }
}