2016-02-16 11 views
5

Mam aplikację, która uruchamia skrypty Lua. Każdy skrypt Lua prawdopodobnie będzie działał kilka razy. Niektóre skrypty mogą być uruchamiane za każdym naciśnięciem klawisza.Lua - Reseting stanu skryptu bez jego reparacji

Chciałbym, aby te skrypty zostały "zresetowane" pomiędzy kolejnymi uruchomieniami. Jeżeli użytkownik ustawi zmienną Foo, to Foo nie powinno istnieć w skrypcie przy następnym uruchomieniu, dopóki użytkownik nie zdefiniuje go ponownie.

Problem polega na tym, że jeśli chcę mieć takie zachowanie, muszę za każdym razem tworzyć nowe lua_State, a następnie otwierać za każdym razem biblioteki, a następnie analizować plik skryptowy za każdym razem, co wydaje się bardzo nieoptymalizowane.

Ładowanie bibliotek może być raczej lekką operacją (jak zakładam), ale parsowanie skryptów prawdopodobnie nie jest.

Czy istnieje sposób, aby przywrócić stan skryptu Lua (to jasne kod użytkownika zdefiniowane zmienne) bez tworzenia nowego lua_State i ponownej analizy składniowej cały plik skryptowy Lua? Chciałbym tylko, aby pliki skryptów były analizowane podczas uruchamiania aplikacji, ponieważ nie są modyfikowane w czasie wykonywania.

Dziękuję. :)

EDIT: Znalazłem ten temat, ale to nie jest szczegółowo o to zrobić: http://lua-users.org/lists/lua-l/2006-01/msg00493.html

EDIT: lua_setfenv wydaje się być związane z tym. Jeszcze trochę wykopię.

EDIT: Wygląda na to, że nie ma już lua_setfenv jak LUA 5.2. Ponieważ używam 5.3, musiałbym ustawić środowisko (tj. Ukrytą tabelę nazwaną _ENV, w której zmienne są przechowywane), aby to zrobić, i w ten sposób ponownie załadować wszystko, czego nie chcę robić ...

+0

Możesz to zrobić po stronie Lua z coroutinami? – warspyking

Odpowiedz

1

Ostatnim razem, gdy się nad tym zastanawiałem, odpowiedź była niestety niestety.

Trzeba także pamiętać, że Lua mogą dzwonić bibliotek, które mogą otworzyć plików, malloc() pamięć itd, a wszelkie „resetu” musi radzić sobie z zamknięciem tych plików, uwalniając że pamięć itp

Jako alternatywę dla "resetowania" stanu Lua, możesz po prostu uporządkować swój kod tak, aby nie wymagał resetowania; to oczywiście wymaga napisania kodu Lua w określony sposób. Jednym ze sposobów na to byłoby podkreślenie, że twój kod Lua był całkowicie (lub prawie całkowicie) zawarty w funkcjach i wywoływał jedną lub więcej funkcji dla każdego działania. Kod spoza funkcji może (na przykład) zwrócić tabelę Lua zawierającą odwołania do wywoływania określonych punktów wejścia; to można nazwać tylko raz. Funkcja (s), po wywołaniu, wyczyściła się po sobie, włączając w to wyczyszczenie dowolnych przydzielonych bibliotek, otwartych plików itd. Należy unikać zmiennych globalnych (chyba że stała). Z powodzeniem używamy tego podejścia, aby Lua była analizowana tylko raz, punkty wejścia są określane raz, ale względne małe funkcje można nazwać bardzo szybko przy niewielkim obciążeniu.

W komentarzach, które zasugerowałeś, możesz leksykalnie owinąć kod Lua w blok funkcyjny.Myślę, że to jest mniej elastyczny niż powyższego podejścia, i ma następujące wady:

  • tracisz możliwość zrobienia „jednego Init czasu” (np na przykład czytanie stałe zmienia się z dysku)

  • ryzykujesz nieprzewidywalne rzeczy jeżeli wkładki użytkownika (np) niedopasowanych end ... function B() w kodzie

  • można ograniczyć się do jednego punktu wejścia na stanie Lua.

To znaczy, że kod Lua musi być napisany w inny sposób (w istocie koder Lua dostarcza kod w wymaganej formie). Jednym z możliwych sposobów jest użycie stałego szkieletu do wykonania tego i require w kodzie przeznaczonym do wywoływania jako biblioteki. Nie próbowałem tego podejścia.

+0

Dzięki za pomoc. Jeśli niektóre biblioteki alokują zasoby, czy te zasoby nie powinny być automatycznie usuwane/usuwane podczas usuwania wszystkich zmiennych użytkownika? Czy mogę też ręcznie usunąć wszystkie wartości w _ENV przed uruchomieniem skryptu i zrobić coś w stylu lua_settop (0), aby zresetować stos? – Virus721

+0

I inne pytanie, które może rozwiązać mój problem w inny sposób: co zrobić, jeśli wszystkie zmienne utworzone przez użytkownika są zdefiniowane przy użyciu lokalnego, a następnie skrypty zapakowane w funkcję przed analizą? Gdy funkcja się skończy, wszyscy jej mieszkańcy zostaną zniszczeni, prawda? – Virus721

+0

@ Virus721 - na pewno, jeśli program sam się zresetuje (lub raczej nie potrzebuje resetowania), to by działało. To, co robimy, jest bardzo podobne do tego, że na poziomie globalnym po prostu zwraca wskaźnik do funkcji (IIRC - dawno temu, odkąd się na to patrzyłem), i ta funkcja powinna sama działać w sposób, który jest czyszczony po samo. Ale nie jestem pewien, czy istnieje sposób zresetowania * dowolnego programu * Lua spoza programu. Nie sądzę, że podejście "usuń wszystkie zmienne użytkownika" będzie latać, ponieważ być może trzeba znać kolejność ich usuwania. – abligh

0

Nie możesz wyczyścić lua_State? Usuń wszystkie wątki i ręcznie ustawione globale. Może być konieczne oddzielenie środowiska użytkownika od środowiska globalnego.

+0

Czy "środowisko użytkownika" jest seprate z lua_State? – Virus721

+0

Istnieje globalne środowisko, które zawiera rzeczy jako "tabelę" i "drukowanie" itd. W zależności od implementacji, jest to również środowisko użytkownika. Jeśli użytkownik wykona '' a = 123''', istnieje pole _a_ w środowisku globalnym. Możesz oddzielić go po stronie C (nie wiem jak) lub po stronie Lua, za pomocą prostego getfenv/setfenv (lub _ENV), tworząc nowe środowisko z metapliką __indeks wskazującą na starą. – EinsteinK

Powiązane problemy