Lua не имеет никаких встроенных средств отладки. Вместо этого, это предлагает
специальный интерфейс, посредством функций и обработчиков прерываний, который
позволяет создание различных видов отладчиков, профилировщиков и других
инструментальных средств, которые нуждаются во внутренней информации из
интерпретатора. Этот интерфейс объявлен в файле заголовков
luadebug.h
.
Основная функция, чтобы получить информацию относительно стека интерпретатора:
int lua_getstack (lua_State *L, int level, lua_Debug *ar);Это заполняет части структуры
lua_Debug
с идентификацией записи активации функции, выполняющейся в заданном уровне. Уровень 0
текущая функция управления, в то время как уровень n+1 функция, которая
вызвала уровнем n. Обычно lua_getstack
вернет 1, когда
вызвана с уровнем больше, чем глубина стека, она возвращает 0.
Структура lua_Debug
используется, чтобы
нести различные части информации относительно активной функции:
typedef struct lua_Debug { const char *event; /* "call", "return" */ int currentline; /* (l) */ const char *name; /* (n) */ const char *namewhat; /* (n) поля, глобальные и локальные переменные, методы тэгов */ int nups; /* (u) количество upvalues */ int linedefined; /* (S) */ const char *what; /* (S) "Lua" функция, "C" функция, Lua "main" */ const char *source; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ ... } lua_Debug;
lua_getstack
заполняет только одну из частей этой структуры
для будущего использования. Чтобы заполнить другие поля lua_Debug
полезной информацией, надо вызвать:
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);Эта функция возвращает 0 на ошибке (например, недопустимая опция в
what
). Каждый символ в строке what
указывает некоторые
поля ar
, которые будет заполнены, как обозначено символом в круглых
скобках в определении lua_Debug
: S
заполняет поле
исходником (source
), linedefined
и what
, l
заполняет поле текущей строкой (currentline
) и так
далее. Кроме того, f
помещает в стек функцию, которая работает в
данном уровне.
Чтобы добираться до информации относительно функции, которая не активна (то
есть она не в стеке), Вы помещаете функцию в стек и начинаете строку
what
с символа >
. Например, чтобы знать, в которой
строке функция f
была определена, Вы можете писать:
lua_Debug ar; lua_getglobal(L, "f"); lua_getinfo(L, ">S", &ar); printf("%d\n", ar.linedefined);Поля
lua_Debug
имеют следующее значение:
source
как раз и будет
этой строкой, а если функция была определена в файле, source
начинается с @
, а дальше имя файла.
source
, чтобы использоваться в
сообщениях об ошибке.
"Lua"
, если это функция Lua, "C"
, если
это функция C или "main"
, если это основная часть chunk.
currentline
установлен в -1.
lua_getinfo
проверяет,
является ли данная функция методом тэга или значением глобальной переменной.
Если данная функция представляет собой метод тэга, name
указывает
на имя события. Если данная функция является значением глобальной переменной,
то name
указывает на имя переменной. Если данная функция не
является ни методом тэга, ни глобальной переменной, то name
установлен в NULL
.
namewhat
равен "global"
. Если функция метод тэга,
namewhat
равен "tag-method"
, иначе
namewhat
равен ""
(пустой строке).
Для манипулирования локальными переменными luadebug.h
использует
индексы: первый параметр или локальная переменная имеет индекс 1 и так далее до
последней активной локальной переменной.
Следующие функции позволяют манипулировать локальными переменными данной активной записи.
const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);Параметр
ar
должен быть имеющей силу записью активации,
заполненной предыдущим обращением к lua_getstack
или данный как
параметр обработчика прерываний. Функция lua_getlocal
получает
индекс локальной переменной (n
), помещает значение в стек и
возвращает имя. Для lua_setlocal
Вы помещаете новое значение в
стек, а функция назначает это значение переменной и возвращает имя. Обе функции
возвращают NULL
при сбое. Это случается, если заданный индекс
больше, чем число активных локальных переменных.
Как пример, следующая функция вносит в список имена всех локальных переменных функции в данном уровне стека:
int listvars (lua_State *L, int level) { lua_Debug ar; int i = 1; const char *name; if (lua_getstack(L, level, &ar) == 0) return 0; /* failure: no such level in the stack */ while ((name = lua_getlocal(L, &ar, i++)) != NULL) { printf("%s\n", name); lua_pop(L, 1); /* remove variable value */ } return 1; }
Lua-интерпретатор предлагает два обработчика прерываний для целей отладки: call и line. Оба обработчика имеют тот же самый тип:
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);Вы можете устанавливать их со следующими функциями:
lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); lua_Hook lua_setlinehook (lua_State *L, lua_Hook func);Обработчик прерываний заблокирован, когда значение
NULL
, что
и является начальным значением обоих обработчиков прерываний. Функции lua_setcallhook
и lua_setlinehook
устанавливают
соответствующие обработчики прерываний и возвращают их предыдущие значения.
Обработчик прерываний call вызван всякий раз, когда интерпретатор вызывает
или оставляет функцию. Поле события event
записи ar
имеет строки "call"
или "return"
. Этот ar
может затем использоваться в обращениях для lua_getinfo
,
lua_getlocal
и lua_setlocal
, чтобы получить большее
количество информации относительно функции и управлять локальными переменными.
Обработчик прерываний line вызван каждый раз, когда интерпретатор изменяет
строку кода, которую выполняет. Поле event
в ar
имеет
строку "line"
, а поле currentline
хранит код строки.
Вы можете использовать этот ar
в других обращениях к отладочному
API.
В то время как Lua управляет обработчиком прерываний, это отключает другие обращения к обработчикам прерываний. Следовательно, если обработчик прерываний вызывает Lua, чтобы выполнить функцию или chunk, это выполнение идет без обращений к обработчикам прерываний.
Библиотека ldblib
обеспечивает функциональные возможности
интерфейса отладки программам Lua. Если Вы хотите использовать эту библиотеку,
Ваша ведущая прикладная программа должна открыть ее вызовом
lua_dblibopen
.
Вы должны проявить большую осторожность при использовании этой библиотеки. Функции, обеспеченные здесь, должны использоваться исключительно для отладки и подобных задач (например, профилирования). Пожалуйста, сопротивляйтесь искушению использовать их как обычный инструмент программирования. Они медленны и нарушают некоторые аспекты языка (например, секретность локальных переменных). Как общее правило, если Ваша программа не нуждается в этой библиотеке, не открывайте ее вообще.
Эта функция возвращает таблицу с информацией относительно функции. Вы можете
давать функцию непосредственно, или Вы можете давать число как значение
function
, что означает функциональное управление в уровне стека
function
. Уровень 0 считается текущей функцией (непосредственно
getinfo
), уровень 1: функция, которая вызвала getinfo
и так далее. Если function
представляет собой число большее, чем
число активных функций, то getinfo
сразу вернет nil.
Возвращенная таблица содержит все поля, возвращенные lua_getinfo
со строкой what
описывающий, что нужно получить. Значение по
умолчанию для what
: нужно получить всю доступную информацию.
Например, выражение getinfo(1,"n").name
вернет имя текущей
функции, если приемлемое имя может быть найдено, и getinfo(print)
возвращает таблицу со всей доступной информацией относительно функции
print
.
Эта функция возвращает имя и значение локальной переменной с индексом,
local
на уровне level
стека. Первый параметр или
локальная переменная имеет индекс 1 и так далее до последней активной локальной
переменной. Функция вернет nil, если не имеется никакой локальной
переменной с данным индексом, и поднимает ошибку когда вызвана с
level
вне диапазона. Вы можете вызывать getinfo
, чтобы
проверить, имеет ли этот уровень силу.
Эта функция назначает значение value
локальной переменной с
индексом local
функции на уровне level
стека. Функция
вернет nil, если не имеется никакой локальной переменной с данным
индексом, и поднимает ошибку когда вызвана с уровнем level
вне
диапазона.
Устанавливает функциональный обработчик прерываний hook
как
обработчик прерываний call. Этот обработчик прерываний будет вызван каждый раз
при начале и завершении интерпретации функции. Единственный параметр на
обработчик прерываний call: имя события ("call"
или
"return"
). Вы можете вызывать getinfo
с уровнем 2,
чтобы получить большее количество информации относительно функции (уровень 0
соответствует функции getinfo
, а уровень 1 задает функцию
обработчика прерываний. Когда вызвана без параметров, эта функция выключает
обработчики прерываний call. setcallhook
вернет старый обработчик
прерываний.
Устанавливает функциональный обработчик прерываний hook
как
обработчик прерываний line. Этот обработчик прерываний будет вызван каждый раз,
когда интерпретатор изменяет обрабатываемую строку кода. Единственный параметр
на обработчике прерываний line: код строки, которую интерпретатор собирается
выполнять. Когда вызвана без параметров, эта функция выключает обработчики
прерываний line. Вызов setlinehook
возвращает старый обработчик
прерываний.