Reputation: 10040
Is there a way to determine how many parameters a Lua function takes just before calling it from C/C++ code?
I looked at lua_Debug
and lua_getinfo
but they don't appear to provide what I need.
It may seem a bit like I am going against the spirit of Lua but I really want to bullet proof the interface that I have between Lua and C++. When a C++ function is called from Lua code the interface verifies that Lua has supplied the correct number of arguments and the type of each argument is correct. If a problem is found with the arguments a lua_error
is issued.
I'd like to have similar error checking the other way around. When C++ calls a Lua function it should at least check that the Lua function doesn't declare more parameters than are necessary.
Upvotes: 4
Views: 1978
Reputation: 16753
You can determine the number of parameters, upvalues and whether the function accepts variable number of arguments in Lua 5.2, by using the 'u'
type to fill nups, nparams, isvararg
fields by get_info(). This feature is not available in Lua 5.1.
Upvotes: 5
Reputation: 1282
The information you ask for is not available in all cases. For example, a Lua function might actually be implemented in C as a lua_CFunction. From Lua code there is no way to distinguish a pure Lua function from a lua_CFunction. And in the case of a lua_CFunction, the number of parameters is not exposed at all, since it's entirely dependent on the way the function is implemented.
On the other hand, what you can do is provide a system for functions writers (be it in pure Lua or in C) to advertise how many parameters their functions expect. After creating the function (function f(a, b, c) end) they would simply pass it to a global function (register(f, 3)). You would then be able to retrieve that information from your C++ code, and if the function didn't advertise its parameters then fallback to what you have now. With such a system you could even advertise the type expected by the parameters.
Upvotes: 1
Reputation: 41403
I wouldn't do this on the Lua side unless you're in full control of Lua code you're validating. It is rather common for Lua functions to ignore extra arguments simply by omitting them.
One example is when we do not want to implement some methods, and use a stub function:
function do_nothing() end
full_api = {}
function full_api:callback(a1, a2) print(a1, a2) end
lazy_impl = {}
lazy_impl.callback = do_nothing
This allows to save typing (and a bit of performance) by reusing available functions.
If you still want to do function argument validation, you have to statically analyze the code. One tool to do this is Metalua.
Upvotes: 2
Reputation: 43326
No, not within standard Lua. And is Aaron Saarela is saying, it is somewhat outside the spirit of Lua as I understand it. The Lua way would be to make sure that the function itself treats nil
as a sensible default (or converts it to a sensible default with something like name = name or "Bruce"
before its first use) or if there is no sensible default the function should either throw an error or return a failure (if not name then error"Name required" end
is a common idiom for the former, and if not name then return nil, "name required" end
is a common idiom for the latter). By making the Lua side responsible for its own argument checks, you get that benefit regardless of whether the function is called from Lua or C.
That said, it is possible that your modules could maintain an attribute table indexed by function that contains the info you need to know. It would require maintenance, of course. It is also possible that MetaLua could be used to add some syntax sugar to create the table directly from function declarations at compile time. Before calling the Lua function, you would use it directly to look up any available attributes and use them to validate the call.
If you are concerned about bullet-proofing, you might want to control the function environment to use some care with what (if any) globals are available to the Lua side, and use lua_pcall()
rather than lua_call()
so that you catch any thrown errors.
Upvotes: 1
Reputation: 4036
What you're asking for isn't possible in Lua.
You can define a Lua function with a set of arguments like this:
function f(a, b, c)
body
end
However, Lua imposes no restrictions on the number of arguments you pass to this function.
This is valid:
f(1,2,3,4,5)
The extra parameters are ignored.
This is also valid:
f(1)
The remaining arguments are assigned 'nil'.
Finally, you can defined a function that takes a variable number of arguments:
function f(a, ...)
At which point you can pass any number of arguments to the function.
See section 2.5.9 of the Lua reference manual.
The best you can do here is to add checks to your Lua functions to verify you receive the arguments you expect.
Upvotes: 5