Экспорт и импорт -- концепция, введённая в версии .023,
реализованная для осуществления взаимодействия между разными активными скриптами, позволяет обмениваться данными и вызывать функции. Самое наглядное применение данной системы -- это создание API, но область применения этим не ограничивается.
Не является альтернативой или заменой стандартной функции require
.
В одном скрипте указывается, что он экспортирует какие-то данные, будь то обычные числа или строки, либо таблицы и функции.
Таким образом он открывает доступ к каким-то своим данным для других скриптов, затем другие скрипты могут обращаться к экспортированным данным этого скрипта и взаимодействовать с ним.
Экспортирование данных осуществляется добавлением значений в глобальную таблицу EXPORTS
, либо прямым назначением переменной EXPORTS любого значения [1].
Экспорт -- операция предоставления открытого доступа.
Давайте рассмотрим скрипт, экспортирующий данные. Назовём его exporter.lua
:
local shared_value = 0
-- можно добавлять экспорты таким способом
EXPORTS = {
api_version = 1.0,
static_text_value = 'exports example',
useless_function = function()
end
}
-- и таким
function EXPORTS.print_name()
print(thisScript().name)
end
function EXPORTS.set_shared_value(new_value)
shared_value = new_value
end
function EXPORTS.get_shared_value()
return shared_value
end
-- только все функции и значения, находящиеся в таблице EXPORTS будут доступны другим скриптам
local vk = require 'vkeys'
function main()
while true do
wait(0)
if wasKeyPressed(vk.VK_1)
-- но НЕЛЬЗЯ это делать таким способом
-- почему - об этом ниже
EXPORTS.some_value = 1337
end
if wasKeyPressed(vk.VK_OEM_PLUS) then
-- однако можно обновлять какое-то внутреннее значение и предоставить возможность получать и изменять его посредством функций
shared_value = shared_value + 1
end
if wasKeyPressed(vk.VK_ENTER) then
print(shared_value)
end
end
end
Такой скрипт не будет ничем отличаться от любого другого, пока какой-то из скриптов не импортирует его.
Импорт осуществляется двумя способами: функцией import или обращением к свойству LuaScript.exports объекта LuaScript
. В большинстве случаев рекомендуется использовать функцию import
.
Импорт -- операция получения доступа к экспортированным данным.
Следующий скрипт импортирует предыдущий скрипт exporter.lua
и взаимодействует с ним:
local exporter = import('exporter.lua') -- можно и без расширения
local vk = require 'vk'
function main()
-- экспортирующий скрипт выведет своё название от своего имени.
-- т.е. любая экспортируемая функция выполняется внутри экспортирующего скрипта
exporter.print_name()
-- можно получать значения констант напрямую
print('exporter.lua API Version:', exporter.api_version, 'text:', exporter.static_text_value)
while true do
wait(0)
if wasKeyPressed(vk.VK_2) then
-- будет сгененрировано случайное значение и это значение будет передано функции EXPORTS.set_shared_value из скрипта exporter.lua.
exporter.set_shared_value(math.random(1, 1337))
-- можно вызвать EXPORTS.get_shared_value из exporter.lua и вывести полученное значение
print(exporter.get_shared_value())
end
end
end
Первое импортирование скрипта приводит к полному копированию (кроме функций) его экспортируемых данных в импортирующий скрипт, а повторное импортирование будет возвращать уже загруженные значения. Именно поэтому изменение значений экспортов становится бессмысленным после первого импортирования, и это может привести к несоответствиям между скриптами, если какой-то скрипт загрузит список импортов рано, а другой с задержкой. В связи с этим для правильной реализации доступа к изменяющимся данным нужно использовать функции.
В отличие от стандартной функции require
, функция import
следует системным правилам навигации по пути файла (require
использует точку в качестве разделителя директорий), т.е. путь к экспортируемому скрипту может быть любым путём, поддерживаемым операционной системой. Правила поиска файла по заданному пути такие же, как у функции script.load.
экспортировать и передавать другому скрипту можно любые значения, в т.ч. вложенные таблицы и функции, но обмен потоками (thread), и пользовательскими данными (userdata) приведёт к неопределённому поведению ↩︎