Возврат таблицы lua по вызову SWIG - PullRequest
0 голосов
/ 01 мая 2010

У меня есть класс с методом GetEnemiesLua. Я связал этот класс с lua, используя SWIG, и я могу вызвать этот метод, используя мой код 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

Результат всегда 'n is nil', несмотря на то, что это неверно. Я поставил точки останова в коде, и он действительно идет по циклу, а не делает lua_pushnil.

Так как мне заставить мой метод возвращать таблицу при вызове через lua?

Ответы [ 2 ]

1 голос
/ 06 мая 2010

Ваша функция 'GetEnemies' возвращает void, который SWIG примет буквально, отбрасывая все значения, которые вы пытаетесь вернуть. Вы захотите указать свою функцию 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;
    }
}
1 голос
/ 01 мая 2010

Бог знает, что делает SWIG (API Lua настолько прост, что я избегаю SWIG и его маленьких друзей), но где-то вам нужно сообщить Lua, что вы не только оставляете стол на вершине стека, но вы хотите вернуть эту таблицу. Если бы вы писали код C самостоятельно, return 1; сделал бы это. Я не знаю, как убедить SWIG заставить его вернуть вам значение, но держу пари, что тип возврата void не приносит вам никакой пользы.

Вы можете попробовать обойти SWIG и просто создать функцию с прототипом

int lua_get_enemies(lua_State *L);

Если затем вы можете заставить работать свой внутренний материал, просто завершите процедуру с помощью return 1;, и таблица в верхней части стека может сделать это.

...