Доступ к телу функции с помощью Lua
-
21-08-2019 - |
Вопрос
Здесь я возвращаюсь к основам, но в Lua вы можете определить таблицу следующим образом:
myTable = {}
myTable [1] = 12
Печать самой ссылки на таблицу возвращает указатель на нее.Чтобы получить доступ к его элементам, вам необходимо указать индекс (т.е.точно так же, как вы сделали бы с массивом)
print(myTable ) --prints pointer
print(myTable[1]) --prints 12
Теперь функции - это совсем другая история.Вы можете определить и распечатать функцию следующим образом:
myFunc = function() local x = 14 end --Defined function
print(myFunc) --Printed pointer to function
Есть ли способ получить доступ к телу определенной функции?Я пытаюсь собрать небольшой визуализатор кода и хотел бы "заполнить" данную функцию специальными функциями / переменными, чтобы позволить визуализатору "подключать" себя к коду, мне нужно было бы иметь возможность переопределять функцию либо из переменной, либо из строки.
Решение
Нет никакого способа получить доступ к основному исходному коду данной функции в обычном Lua.Исходный код выбрасывается после компиляции в байт-код.
Обратите внимание, кстати, что функция может быть определена во время выполнения с помощью средства, подобного loadstring.
Возможны частичные решения — в зависимости от того, чего вы на самом деле хотите достичь.
Вы можете получить позицию исходного кода из библиотеки отладки — если включена библиотека отладки и символы отладки не удалены из байт-кода.После этого вы можете загрузить фактический исходный файл и извлечь оттуда код.
Вы можете вручную дополнить интересующие вас функции необходимыми метаданными.Обратите внимание, что функции в Lua являются допустимыми ключами таблицы, поэтому вы можете создать таблицу "функция-метаданные".Вы бы хотели сделать эту таблицу со слабым ключом, чтобы это не препятствовало сбору функций с помощью GC.
Если вам нужно решение для анализа кода Lua, взгляните на Металлия.
Другие советы
Использование библиотеки отладки - это ваш единственный выбор.Используя это, вы можете получить либо строку (если функция определена в фрагменте, который был загружен с помощью 'loadstring'), либо имя файла, в котором была определена функция;вместе с номерами строк, с которых начинается и заканчивается определение функции.Смотрите на Документация.
Здесь, на моей текущей работе, мы исправили Lua так, что он даже выдает вам номера столбцов для начала и конца функции, так что вы можете получить источник функции, используя это.Воспроизвести патч не очень сложно, но я не думаю, что мне разрешат опубликовать его здесь :-(
Проверьте Возможности для самоанализа Lua в библиотеке отладки.
Основной функцией самоанализа в библиотеке отладки является debug.getinfo функция.Его первым параметром может быть функция или уровень стека.Когда вы вызываете debug.getinfo(foo) для некоторой функции foo, вы получаете таблицу с некоторыми данными об этой функции.В таблице могут содержаться следующие поля:
Я думаю, поле, которое вам нужно, - это func.
Вы могли бы достичь этого, создав Окружающая среда для каждой функции (см. setfenv ( настройка )) и использование глобальных (по сравнению с локальными) переменных.Переменные, созданные в функции, затем появятся в таблице среды после выполнения функции.
env = {}
myFunc = function() x = 14 end
setfenv(myFunc, env)
myFunc()
print(myFunc) -- prints pointer
print(env.x) -- prints 14
В качестве альтернативы, вы могли бы воспользоваться Библиотека отладки:
> myFunc = function() local x = 14 ; debug.debug() end
> myFunc()
> lua_debug> _, x = debug.getlocal(3, 1)
> lua_debug> print(x) -- prints 14
Вероятно, для вас было бы более полезно получить локальные переменные с помощью функция крючка вместо явного входа в режим отладки (т.е.добавление debug.вызов debug())
Существует также Интерфейс отладки в API Lua C.