Я работаю над улучшением способа обработки Lua-скриптов для роботов в Bitfighter. В настоящее время каждый робот получает свой собственный экземпляр L, и мы пытаемся заставить их использовать общий доступ, заменяя таблицы среды. Обратите внимание, что боты могут быть совершенно разными сценариями.Lua, metatables и глобальные переменные
Я понимаю, что этот метод устарел в Lua 5.2, но в настоящее время мы используем lua-vec, который все еще использует Lua 5.1. Игра написана на C++.
Итак ...
Сначала мы создаем среду, и называют его:
// Create a table with room for 0 array and 1 non-array elements
lua_createtable(L, 0, 1); // -- tab
// Set the globals table to handle any requests that the
// script's environment can't
lua_pushstring(L, "__index"); // -- tab, "__index"
lua_pushvalue(L, LUA_GLOBALSINDEX); // -- tab, "__index", _G
// Set table["__index"] = _G, pops top two items from stack
lua_settable(L, -3); // -- tab
// Store the new table in the retistry for future use
lua_setfield(L, LUA_REGISTRYINDEX, name); // -- <<empty stack>>
Позже мы загружаем некоторые Lua код и вспомнить среды таблицу:
luaL_loadfile(L, "luascripts.lua");
lua_getfield(L, LUA_REGISTRYINDEX, name); // -- function, table
lua_setfenv(L, -2); // -- function
Затем запустите загруженный код:
lua_pcall(L, 0, 0, 0);
Когда загружен Lua пытается использовать основные функции, такие как печать, он терпит неудачу с ошибкой:
attempt to call global 'print' (a nil value)
Но сценарий может сделать следующее:
__index["print"](12)
Так .. почему мы не можем напрямую обращаться к печати? Что нам не хватает? Или существует принципиально лучший способ запуска нескольких сценариев в одном экземпляре Lua?
Спасибо за ваш ответ! «Еще один способ - создать таблицу окружения для каждого скрипта ...», это именно то, что я пытаюсь сделать, хотя я и не думал предоставить каждому сценарию копию таблицы глобальных таблиц. Я вижу из вашего примера, почему это улучшит безопасность и изоляцию скрипта, но я не уверен, как это реализовать, и я не нашел хороших примеров реализаций, несмотря на значительные исследования. – Watusimoto
@Watusimoto: На самом деле это довольно просто. Вы просто скопируете каждый элемент белого списка из глобальной таблицы в таблицу окружения (и когда вы переходите к изменяемым элементам, вы должны правильно скопировать элементы, а не только ссылки). Я вернусь через несколько дней и приведу несколько подходящих примеров. (Пожалуйста, напомните мне, поэтому я не забываю!) – Mankarse
Спасибо. Это должно быть относительно простым, так как моя таблица глобальных таблиц уже ограничена функциями и значениями, к которым я хочу, чтобы скрипты имели доступ, поэтому это будет операция с копией. – Watusimoto