2010-05-01 54 views
0

我有一個名爲GetEnemiesLua的方法。我已經使用SWIG將此類綁定到lua,並且可以使用我的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 

的結果總是「 t是零「,儘管這是不正確的。我在代碼中加入了斷點,它確實在循環中,而不是在執行lua_pushnil

那麼如何讓我的方法通過lua調用時返回表?

回答

1

您的'GetEnemies'函數返回無效,哪個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; 
    } 
} 
+0

現在這是一個更加優雅的解決方案^ _ ^ – 2010-05-06 15:42:25

1

上帝只知道SWIG在做什麼(Lua API非常簡單,我避免了SWIG和它的小朋友),但是在某個地方你需要與Lua溝通,你不僅要在棧頂留下一張桌子,但是你想返回那個表。如果你自己寫的C代碼return 1;會做到這一點。我不知道如何說服SWIG讓它爲你回報價值,但我敢打賭,返回類型void對你沒有任何好處。

你可以嘗試圍繞SWIG工作,只是創建原型

int lua_get_enemies(lua_State *L); 

的功能。如果你就可以得到你內心的東西去上班,就結束在堆棧的頂部return 1;常規,表可能會這樣做。

+0

如果我改變它返回1,然後在我的teast代碼,T不會是一個表,我想,但一些文字,並打印它會生成字符串「1」 – 2010-05-01 18:48:11

+0

@湯姆:我也很擔心。那麼,我希望有人能夠理解SWIG的複雜性。你幾乎肯定需要用其他東西來替換那個'void'返回類型。但是要考慮嘗試直接的Lua API--它確實非常令人愉快,並且很容易計算出來。 – 2010-05-01 18:54:38