4

有没有办法在从 C/C++ 代码调用 Lua 函数之前确定它需要多少个参数?

我看了看,lua_Debuglua_getinfo他们似乎没有提供我需要的东西。

看起来我有点违背 Lua 的精神,但我真的想证明我在 Lua 和 C++ 之间的接口。当从 Lua 代码调用 C++ 函数时,接口会验证 Lua 提供了正确数量的参数以及每个参数的类型是否正确。如果发现参数有问题,lua_error则发出 a。

我想反过来检查类似的错误。当 C++ 调用 Lua 函数时,它至少应该检查 Lua 函数没有声明过多的参数。

4

5 回答 5

5

在 Lua 5.2 中,您可以通过 get_info()'u'使用类型填充字段来确定参数的数量、上值以及函数是否接受可变数量的参数。此功能在 Lua 5.1 中不可用。nups, nparams, isvararg

于 2011-11-11T14:21:03.410 回答
5

你所要求的在 Lua 中是不可能的。

您可以使用一组参数定义一个 Lua 函数,如下所示:

function f(a, b, c)
   body
end

但是,Lua 对传递给此函数的参数数量没有限制。

这是有效的:

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

额外的参数被忽略。

这也是有效的:

f(1)

其余参数分配为“nil”。

最后,您可以定义一个接受可变数量参数的函数:

function f(a, ...)

此时,您可以将任意数量的参数传递给函数。

请参阅Lua 参考手册的第 2.5.9 节。

您可以在这里做的最好的事情是向您的 Lua 函数添​​加检查,以验证您收到了您期望的参数。

于 2009-04-24T13:44:26.400 回答
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

于 2009-04-30T06:10:39.793 回答
1

不,不在标准 Lua 中。并且是 Aaron Saarela 所说的,据我所知,这有点超出了 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()捕获任何抛出的错误。

于 2009-04-24T20:25:20.117 回答
1

您要求的信息并非在所有情况下都可用。例如,一个 Lua 函数实际上可能在 C 中实现为 lua_CFunction。从 Lua 代码中无法区分纯 Lua 函数和 lua_CFunction。而在 lua_CFunction 的情况下,参数的数量根本不会暴露,因为它完全取决于函数的实现方式。

另一方面,您可以做的是为函数编写者(无论是纯 Lua 还是 C 语言)提供一个系统来宣传他们的函数需要多少参数。在创建函数 (function f(a, b, c) end) 后,他们只需将其传递给全局函数 (register(f, 3))。然后,您将能够从您的 C++ 代码中检索该信息,并且如果该函数没有公布其参数,则回退到您现在所拥有的。使用这样的系统,您甚至可以宣传参数所期望的类型。

于 2009-04-30T10:21:36.010 回答