Есть ли способ программно определить в C/С++, сколько параметров ожидает функция Lua?

Есть ли способ определить, сколько параметров принимает функция Lua непосредственно перед ее вызовом из кода C/C++?

Я посмотрел на lua_Debug и lua_getinfo, но они не дают того, что мне нужно.

Может показаться, что я иду против духа Lua, но я действительно хочу пуленепробиваемый интерфейс, который у меня есть между Lua и C++. Когда функция C++ вызывается из кода Lua, интерфейс проверяет, что Lua предоставил правильное количество аргументов и правильный тип каждого аргумента. Если обнаружена проблема с аргументами, выдается lua_error.

Я бы хотел, чтобы аналогичная ошибка проверялась наоборот. Когда C++ вызывает функцию Lua, он должен, по крайней мере, проверить, что функция Lua не объявляет больше параметров, чем необходимо.


person Ashley Davis    schedule 24.04.2009    source источник


Ответы (5)


То, о чем вы просите, невозможно в Lua.

Вы можете определить функцию Lua с таким набором аргументов:

function f(a, b, c)
   body
end

Однако Lua не накладывает ограничений на количество аргументов, которые вы передаете этой функции.

Это действительно:

f(1,2,3,4,5)

Дополнительные параметры игнорируются.

Это также справедливо:

f(1)

Остальным аргументам присваивается значение «ноль».

Наконец, вы можете определить функцию, которая принимает переменное количество аргументов:

function f(a, ...)

В этот момент вы можете передать любое количество аргументов функции.

См. раздел 2.5.9 справочного руководства по Lua.

Лучшее, что вы можете здесь сделать, это добавить проверки к вашим функциям Lua, чтобы убедиться, что вы получаете ожидаемые аргументы.

person Aaron Saarela    schedule 24.04.2009
comment
Ну, я сказал, что знаю, что то, что я делаю, не в духе Lua :) С функциями, реализованными и вызываемыми полностью в Lua, это будет работать так, как вы говорите, однако то, что я хочу, - это способ усилить интерфейс Lua/C++. Когда вы реализуете интерфейс C++ с помощью функций Lua (используя нашу пользовательскую систему привязки Lua/C++), имеет смысл автоматически обеспечивать, чтобы функции Lua, вызываемые из C++, реализовывали правильное количество аргументов. Тем не менее, я подозреваю, что невозможно делать то, что я хочу. Думал все таки спросить! - person Ashley Davis; 27.04.2009

Вы можете определить количество параметров, повышающих значений и принимает ли функция переменное количество аргументов в Lua 5.2, используя тип 'u' для заполнения nups, nparams, isvararg полей с помощью get_info(). Эта функция недоступна в Lua 5.1.

person Michal Kottman    schedule 11.11.2011

Я бы не стал делать это на стороне Lua, если только вы не полностью контролируете код Lua, который проверяете. Для функций Lua довольно часто игнорируются дополнительные аргументы, просто опуская их.

Один из примеров — когда мы не хотим реализовывать некоторые методы и используем функцию-заглушку:

function do_nothing() end

full_api = {}
function full_api:callback(a1, a2) print(a1, a2) end

lazy_impl = {}
lazy_impl.callback = do_nothing

Это позволяет сократить набор текста (и немного производительности) за счет повторного использования доступных функций.

Если вы все еще хотите выполнять проверку аргументов функции, вам необходимо статически проанализировать код. Одним из инструментов для этого является Metalua.

person Alexander Gladysh    schedule 30.04.2009
comment
Спасибо. Я собираюсь взглянуть на металуа. В моем случае статический анализ кода Lua может оказаться лучше, чем попытка выполнить проверку во время выполнения. - person Ashley Davis; 30.04.2009
comment
Пожалуйста. Если вы это сделаете, напишите в список рассылки Metalua (lists.luaforge.net/ mailman/listinfo/metalua-list). Вполне вероятно, что вы получите ценный совет от автора Metalua. - person Alexander Gladysh; 30.04.2009

Нет, не в рамках стандартного Lua. А Аарон Саарела говорит, что это несколько выходит за рамки духа Lua, как я его понимаю. Путь Lua заключается в том, чтобы убедиться, что сама функция рассматривает nil как разумное значение по умолчанию (или преобразует его в разумное значение по умолчанию с помощью чего-то вроде name = name or "Bruce" перед его первым использованием), или, если разумного значения по умолчанию нет, функция должна либо выдать ошибку, либо вернуть отказ (if not name then error"Name required" end – распространенная идиома для первого, а _4  – для второго). Возлагая на сторону Lua ответственность за собственные проверки аргументов, вы получаете это преимущество независимо от того, вызывается ли функция из Lua или C.

Тем не менее, возможно, что ваши модули могут поддерживать таблицу атрибутов, индексированную функцией, которая содержит информацию, которую вам нужно знать. Конечно, это потребует обслуживания. Также возможно, что MetaLua можно использовать для добавления некоторого синтаксического сахара для создания таблицы непосредственно из объявлений функций во время компиляции. Перед вызовом функции Lua вы должны использовать ее напрямую для поиска любых доступных атрибутов и использовать их для проверки вызова.

Если вы беспокоитесь о пуленепробиваемости, вы можете захотеть контролировать среду функций, чтобы с некоторой осторожностью относиться к тому, какие глобальные переменные (если они есть) доступны для стороны Lua, и использовать lua_pcall(), а не lua_call(), чтобы вы отлавливали любые возникающие ошибки.

person RBerteig    schedule 24.04.2009

Информация, которую вы запрашиваете, доступна не во всех случаях. Например, функция Lua может быть реализована на C как lua_CFunction. В коде Lua невозможно отличить чистую функцию Lua от функции lua_CFunction. А в случае lua_CFunction количество параметров вообще не раскрывается, так как оно полностью зависит от способа реализации функции.

С другой стороны, вы можете предоставить разработчикам функций (будь то на чистом Lua или на C) систему для объявления того, сколько параметров ожидают их функции. После создания функции (функция f(a, b, c) end) они просто передают ее глобальной функции (register(f, 3)). Затем вы сможете получить эту информацию из своего кода на C++, и если функция не объявляет свои параметры, вернитесь к тому, что у вас есть сейчас. С такой системой вы могли бы даже рекламировать тип, ожидаемый параметрами.

person Doub    schedule 30.04.2009
comment
Вы сделали несколько хороших замечаний. Хотя система, которую вы предлагаете во втором абзаце, так же подвержена человеческим ошибкам, как и случай по умолчанию, например, в обычном случае вы должны полагаться на кодировщика, чтобы получить правильные аргументы, во втором случае кодер должен правильно получить оба аргументы и метаданные аргументов. - person Ashley Davis; 30.04.2009