2009-04-24 2 views
3

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

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

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

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

ответ

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 reference manual.

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

+0

Ну, я сказал, что знаю, что я делаю, не в духе Lua :) С функциями, реализованными и вызванными полностью в Lua, он будет работать так, как вы говорите, однако то, что я хочу, - это способ упростить Lua/C++. Когда вы реализуете интерфейс C++ с использованием функций Lua (используя нашу обычную систему привязки Lua/C++), имеет смысл автоматически принудительно выполнять функции Lua, которые вызывают из C++, реализовать правильное количество аргументов. Тем не менее я подозреваю, что делать то, что я хочу, невозможно. Думал, я все равно прошу! –

1

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

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

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

2

Я бы не сделал этого на стороне 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.

+2

Спасибо. Я собираюсь взглянуть на metalua. Статический анализ кода Lua на самом деле может быть лучше в моем случае, чем попытка выполнить проверку во время выполнения. –

+0

Добро пожаловать. Если вы это сделаете, перейдите в список рассылки Metalua (http://lists.luaforge.net/mailman/listinfo/metalua-list). Вероятно, вы получите ценный совет от автора Metalua. –

1

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

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

+0

Вы сделали несколько хороших моментов. Хотя система, которую вы предлагаете во втором абзаце, так же открыта для человеческой ошибки, как и случай по умолчанию, например, в нормальном случае вам приходится полагаться на кодер, чтобы получить правильные аргументы, во втором случае кодер должен получить право как аргументы и аргументы-метаданные. –

4

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

 Смежные вопросы

  • Нет связанных вопросов^_^