2009-09-17 10 views
19

Próbuję załadować tabele z Lua do C++, ale mam problemy z uzyskaniem tego poprawnie. Przechodzę przez pierwszą iterację dobrze, ale potem przy drugim wywołaniu lua_next to się zawiesza. Jakieś pomysły? PlikIterowanie przez tabelę Lua z C++?

Lua:

level = { 1, 2, 3, } 

C++ plik - Najpierw zrobiłam to:

lua_getglobal(L, "level"); 
for(lua_pushnil(L); lua_next(L, 1); lua_pop(L, -2)) 
{ 
    if(lua_isnumber(L, -1)) { 
     int i = (int)lua_tonumber(L, -1); 
     //use number 
    } 
} 
lua_pop(L, 1); 

Potem próbowałem z reference manual:

lua_getglobal(L, "level"); 
int t = 1; 
lua_pushnil(L); 
while(lua_next(L, t)) { 
    printf("%s - %s", 
     lua_typename(L, lua_type(L, -2)), 
     lua_typename(L, lua_type(L, -1))); 
    lua_pop(L, 1); 
} 
lua_pop(L, 1); 

i wreszcie to:

lua_getglobal(L, "level"); 
lua_pushnil(L); 

lua_next(L, 1); 
if(lua_isnumber(L, -1)) { 
    int i = (int)lua_tonumber(L, -1); 
    //use number fine 
} 
lua_pop(L, 1); 

lua_next(L, 1); //crashes 

etc... 

Naturalnie L to lua_State * i ja go inicjuję i parsuję plik w porządku.

Edit: W odpowiedzi na Jesse Beder odpowiedź Próbowałem ten kod, z rejestratorem, ale nadal nie mogę zmusić go do pracy.

co dało następujący wynik:

stack size: 0 
-1 is a table 
-1 is now nil 
-2 is now table 
pred: 1 
loop stuff 
num: 1 
stack size: 3 
-3 is now table 
stack size: 2 
-2 is now table 

Wszystko, co powiedział Jesse, wydaje się prawdziwe. Ale nadal nie udaje się przejść do kolejnej iteracji.

Edit2: Próbowałem skopiować dokładny kod do nowego projektu, omijając wszystkie okoliczne klas i rzeczy mi nie przeszkadzało to tu i tam to działa. Ale tutaj tak nie jest i przetrwa tylko jedno połączenie lua_next.

Edytuj3: Zawęziłem to nieco dalej. Używam hge jako mojego silnika 2D. umieścić cały poprzedni kod w teście funkcję:

test(); //works 
if(hge->System_Initiate()) 
{  
    test(); //fails 
    hge->System_Start(); 
} 

O ile mi zrozumieć HGE nic nie robi z lua. Here to kod źródłowy dla małego testu, który zrobiłem. Źródłem dla hge 1.81 jest here.

Edit4: Wielkość pytania wymyka się spod kontroli, ale nie można mu pomóc. Jest to najmniejszy kod, na jaki udało mi się go zredukować.

extern "C" 
{ 
    #include <lua/lua.h> 
    #include <lua/lualib.h> 
    #include <lua/lauxlib.h> 
} 
#include <hge\hge.h> 

bool frame_func() 
{ 
    return true; 
} 

bool render_func() 
{ 
    return false; 
} 

void test() 
{ 
    lua_State *L = lua_open(); 
    luaL_openlibs(L); 

    if(luaL_dofile(L, "levels.lua")) { 
     lua_pop(L, -1); 
     return; 
    } 
    lua_getglobal(L, "level"); 
    lua_pushnil(L); 

    while(lua_next(L, -2)) { 
     if(lua_isnumber(L, -1)) { 
      int i = (int)lua_tonumber(L, -1); 
      //use number 
     } 
     lua_pop(L, 1); 
    } 
    lua_pop(L, 1); 

    lua_close(L); 
} 

int main() 
{ 
    HGE *hge = hgeCreate(HGE_VERSION); 

    hge->System_SetState(HGE_FRAMEFUNC, frame_func); 
    hge->System_SetState(HGE_RENDERFUNC, render_func); 
    hge->System_SetState(HGE_WINDOWED, true); 
    hge->System_SetState(HGE_SCREENWIDTH, 800); 
    hge->System_SetState(HGE_SCREENHEIGHT, 600); 
    hge->System_SetState(HGE_SCREENBPP, 32); 

    //test(); //works 

    if(hge->System_Initiate()) 
    {  
     test(); //fails 
     hge->System_Start(); 
    } 

    hge->Release(); 

    return 0; 
} 
+0

Więc drugie połączenie z 'lua_next' ulega awarii? To dziwne ... czy masz jakieś informacje na temat debugowania (np. Gdzie dokładnie się to zdarzyło)? Ponadto, aby upewnić się, że wszystko działa poprawnie, należy zalogować klucz na każdym kroku (powinien to być również numer) i edytować tę odpowiedź. –

+0

Dodałem wartość zwracaną przez lua_next. Nie mam żadnych informacji na temat debugowania i tak naprawdę nie wiem jak go dodać ... – Jonas

+0

Ta druga edycja to podpowiedź - sprawdź poprawkę na moją odpowiedź –

Odpowiedz

0

Dlaczego robisz dodatkowy lua_pop(L, 1) na końcu wersji z podręcznika? Rozumiem, że to może być problem, ponieważ wykraczasz poza grubość stosu.

+0

Usuwam tabelę ze stosu, w instrukcji jest tylko indeks do tabeli, ale masz żeby popchnąć i gdzieś go popchnąć. – Jonas

27

Po wywołaniu lua_next, drugim argumentem powinien być indeks tabeli.Skoro jesteś po prostu przesuwając stolik na stos z

lua_getglobal(L, "level"); 

potem połączyć się stos będzie wyglądać

 
-1: table "level" 

(nie +1, ponieważ stos jest zejście do odczytu). Następnie zadzwonić

lua_pushnil(L); 

więc stos będzie

 
-1: key (nil) 
-2: table "level" 

Twój stół jest -2, więc podczas rozmowy lua_next, należy użyć indeksu -2. W końcu, po każdej iteracji, twój stos powinien wyglądać następująco:

 
-1: value 
-2: key 
-3: table "level" 

więc chcesz odczytać wartość (w -1), a następnie włóż ją (tak po prostu pop raz), a następnie zadzwonić lua_next dostać następny klucz . Więc coś jak to powinno działać:

lua_getglobal(L, "level"); 
lua_pushnil(L); 

while(lua_next(L, -2)) { // <== here is your mistake 
    if(lua_isnumber(L, -1)) { 
     int i = (int)lua_tonumber(L, -1); 
     //use number 
    } 
    lua_pop(L, 1); 
} 
lua_pop(L, 1); 

Edycja na podstawie swojej drugiej edycji

Ponieważ działa po usunięciu zewnętrznych rzeczy, ale nie po dodaniu go z powrotem, mój najlepszy przypuszczenie że w jakiś sposób uszkadzasz stos (stos C++ lub stos Lua). Spójrz na naprawdę uważnie na swoje wskaźniki, zwłaszcza gdy manipulujesz stanem lua.

+0

Nie udało mi się go uruchomić - zobacz moją edycję w celu uzyskania informacji. – Jonas

+0

Zawęziłem to dalej, jest jeszcze inna edycja dla ciebie. – Jonas

1

Czytanie instrukcji LUA lua_next powoduje, że mogą wystąpić problemy z używaniem lua_tostring bezpośrednio na kluczu, to znaczy musisz sprawdzić wartość klucza, a następnie zdecydować się na użycie lua_tostring lub lua_tonumber. Więc możesz spróbować tego kodu:

std::string key 
    while(lua_next(L, -2) != 0){ // in your case index may not be -2, check 

    // uses 'key' (at index -2) and 'value' (at index -1) 

    if (lua_type(L, -2)==LUA_TSTRING){ // check if key is a string 
     // you may use key.assign(lua_tostring(L,-2)); 
    } 
    else if (lua_type(L, -2)==LUA_TNUMBER){ //or if it is a number 
     // this is likely to be your case since you table level = { 1, 2, 3, } 
     // don't declare field ID's 
     // try: 
     // sprintf(buf,"%g",lua_tonumber(L,-2)); 
     // key.assign(buf); 
    } 
    else{ 
     // do some other stuff 
    } 
    key.clear(); 
    lua_pop(L,1) 
    } 

Mam nadzieję, że pomoże.