2016-02-16 26 views
5

Tôi có một ứng dụng chạy tập lệnh Lua. Mỗi kịch bản Lua có khả năng chạy nhiều lần. Một số tập lệnh thậm chí có thể chạy mỗi lần nhấn một phím.Lua - Khôi phục trạng thái của tập lệnh mà không cần sửa lại nó

Tôi muốn các tập lệnh này được "đặt lại" giữa mỗi lần chạy. I.e nếu người dùng đặt biến Foo, thì Foo sẽ không tồn tại trong tập lệnh vào lần tiếp theo nó chạy cho đến khi người dùng định nghĩa lại nó.

Vấn đề là, nếu tôi muốn có một hành vi như vậy, tôi cần phải tạo một lua_State mới mọi lúc, sau đó mở thư viện vào nó mọi lúc, và sau đó phân tích cú pháp tệp kịch bản mọi lúc, điều này dường như rất không được tối ưu hóa.

Tải thư viện có thể là một hoạt động khá nhẹ (tôi giả định), nhưng việc phân tích cú pháp các tập lệnh có lẽ không phải.

Có cách nào để đặt lại trạng thái của tập lệnh Lua (nghĩa là biến do người dùng xác định rõ ràng) mà không tạo lua_State mới và sửa lại toàn bộ tệp kịch bản Lua không? Tôi chỉ muốn các tệp kịch bản được phân tích cú pháp một lần khi khởi động ứng dụng vì chúng không được sửa đổi vào thời gian chạy.

Cảm ơn bạn. :)

EDIT: Tôi tìm thấy chủ đề này nhưng nó không được trình bày chi tiết về để làm điều đó: http://lua-users.org/lists/lua-l/2006-01/msg00493.html

EDIT: lua_setfenv dường như có liên quan đến đó. Tôi sẽ đào thêm một chút nữa.

EDIT: Dường như không có lua_setfenv nào hơn LUA 5.2. Vì tôi đang sử dụng 5.3, tôi sẽ phải thiết lập môi trường (tức là một bảng ẩn có tên _ENV nơi các biến được lưu trữ) để làm điều đó, và do đó tải lại mọi thứ, đó là những gì tôi không muốn làm ...

+0

Bạn có thể làm điều đó Lua bên với coroutines có lẽ? – warspyking

Trả lời

1

Lần cuối tôi nhìn vào câu trả lời này là không, thật không may.

Bạn cũng cần phải nhớ rằng Lua có thể gọi thư viện, có thể mở các tập tin, bộ nhớ malloc() vv, và rằng bất kỳ 'reset' cần để đối phó với đóng cửa các tập tin, giải phóng bộ nhớ, vv

Để thay thế cho 'đặt lại' trạng thái Lua, bạn có thể chỉ cần sắp xếp mã của mình để mã không cần đặt lại; điều này rõ ràng đòi hỏi mã Lua phải được viết theo một cách cụ thể. Một cách để làm điều đó sẽ là nhấn mạnh mã Lua của bạn là hoàn toàn (hoặc gần như hoàn toàn) chứa trong hàm (s) và gọi một hoặc nhiều chức năng cho mỗi hành động. Mã bên ngoài các hàm có thể (ví dụ) trả về một bảng Lua bao gồm các tham chiếu để gọi cho các điểm vào cụ thể; điều này sẽ chỉ được gọi một lần. (Các) hàm, khi được gọi, sẽ tự động dọn sạch, bao gồm xóa tất cả các mục được phân bổ trong thư viện, các tệp mở, vv Các biến toàn cục nên tránh (trừ khi không đổi). Chúng tôi sử dụng thành công phương pháp này để đảm bảo Lua chỉ được phân tích cú pháp một lần, các điểm vào được xác định một lần, nhưng các hàm tương đối nhỏ có thể được gọi rất nhanh với chi phí thấp.

Trong các nhận xét bạn đã đề xuất, bạn có thể gói gọn mã Lua trong một khối chức năng.Tôi nghĩ rằng đây là ít linh hoạt hơn so với cách tiếp cận trên, và có những nhược điểm sau:

  • Bạn mất cơ hội để làm một 'một lần init' (ví dụ như ví dụ đọc một hằng số cố định từ đĩa)

  • Bạn có thể rủi ro những điều không thể đoán trước nếu người dùng chèn (ví dụ) một số không khớp end ... function B() trong mã của họ

  • Bạn tự giới hạn mình vào một điểm nhập trên mỗi trạng thái Lua.

Mà có nghĩa rằng mã Lua phải được viết bằng một cách khác nhau (trong bản chất các coder Lua đang cung cấp mã theo hình thức bắt buộc). Một cách có thể xung quanh việc này là sử dụng một khung cố định để thực hiện điều này và require trong mã được gọi là thư viện. Tôi đã không thử phương pháp đó.

+0

Cảm ơn sự giúp đỡ của bạn. Nếu một số thư viện phân bổ tài nguyên, không nên các tài nguyên này được tự động phát hành/thu thập rác khi xóa tất cả các biến người dùng? Ngoài ra tôi có thể chỉ đơn giản là tự loại bỏ tất cả các giá trị trong _ENV trước khi chạy một kịch bản và làm một cái gì đó như lua_settop (0) để thiết lập lại ngăn xếp? – Virus721

+0

Và một câu hỏi khác có thể giải quyết vấn đề của tôi theo cách khác: điều gì sẽ xảy ra nếu tất cả các biến do người dùng tạo được định nghĩa bằng cách sử dụng cục bộ và sau đó kịch bản được bao bọc vào một hàm trước khi phân tích cú pháp? Khi chức năng kết thúc, tất cả những người dân địa phương của nó sẽ bị phá hủy đúng không? – Virus721

+0

@ Virus721 - chắc chắn, nếu chương trình có hiệu quả đặt lại chính nó (hoặc thay vì không cần đặt lại), điều đó sẽ hoạt động. Những gì chúng tôi làm là rất giống với điều đó, ở cấp độ toàn cầu, nó chỉ trả về một con trỏ tới một hàm (IIRC - thời gian dài kể từ khi tôi xem nó), và hàm đó sẽ tự chạy theo cách xóa sau chinh no. Nhưng tôi không chắc chắn có một cách để thiết lập lại một chương trình * tùy ý * Lua từ bên ngoài chương trình. Tôi không nghĩ rằng phương pháp 'xóa tất cả biến người dùng' sẽ bay vì bạn cũng có thể cần biết thứ tự để xóa chúng. – abligh

0

Bạn không thể xóa lua_State? Hủy bỏ tất cả các chủ đề và globals thiết lập bằng tay. Bạn có thể cần phải có môi trường người dùng riêng biệt với môi trường toàn cầu.

+0

Dữ liệu "môi trường người dùng" có bị tách khỏi lua_State không? – Virus721

+0

Có một môi trường toàn cục chứa các nội dung như 'bảng' và 'in' vv Tùy thuộc vào việc triển khai, đó cũng là môi trường người dùng. Nếu người dùng có '' 'a = 123''' thì có một trường _a_ trong môi trường toàn cục. Bạn có thể tách nó thành C-side (Tôi không biết làm thế nào) hoặc Lua bên, với một getfenv/setfenv đơn giản (hoặc _ENV), tạo một môi trường mới với một __index metafield trỏ đến cái cũ. – EinsteinK

Các vấn đề liên quan