djsp
djsp

Reputation: 2293

Determine the signature of a Lua function from the C API

A framework I'm working on may be extended with Lua modules. The Lua sources for each module are compiled with a compiler of ours that's based on the official Lua interpreter and then saved as bytecode. Such modules must meet certain requirements:

-- Must be a non-empty string consisting only of characters in the range a-z
name = "foo"

-- Must not only be a number, but also an integer greater than zero
version = 1

It would be nice if the requirements could be checked when the Lua sources are compiled into the module. This would make life easier:

Checking that a certain value is of a certain type is not difficult:

// lua_getglobal returns the type of the value
int r = lua_getglobal(lua_state, "name");
if ( r == LUA_TSTRING )
{
    // well done, dear module writer (well, must still check if the string contains
    // only valid characters)
}
else if ( r == LUA_TNIL )
{
    // error: `name' not defined
}
else
{
    // hey you, `name' should be a string!
}

But how would one go about checking that a function takes a certain number of arguments and returns a table with certain fields?

-- must be defined with two parameters
function valid_function( arg1 , arg2 )
    -- must return a table
    return {
        a = 17, -- with field `a', a number
        b = "a" -- with field `b', a string
    }
end

Note that I'm asking whether this is possible (and, if so, how) with the C API, unlike this question, which is about doing this from within Lua.

Upvotes: 2

Views: 752

Answers (1)

hugomg
hugomg

Reputation: 69944

You cannot do that. Every Lua function can take any number of arguments and return any number of values, of any type.

I think the best you can do is write explicit type annotations somewhere (either in a comment or in something that appears at runtime) and then check that. There is also Typed Lua, which is an experimental Lua dialect with a static type system.


For example of how functions can receive any amount of arguments, if a function receives less arguments than it has parameters, the extra parameters get assigned to nil. If you pass more arguments than the function has as parameters, the extra arguments are discarded.

function foo(x, y)
    print(x,y)
end

foo()      -- prints nil, nil
foo(1)     -- prints 1,   nil
foo(1,2)   -- prints 1,   2
foo(1,2,3) -- prints 1,   2

Having the missing parameters be nil is also commonly used to implement functions with optional parameters which means that a naive attempt at checking the number of arguments will conflict with this common Lua idiom:

function hello(name)
    name = "mysterious stranger"
    print("Hello, "..name.."!")
end

Return arguments are also flexible, just like the input arguments are:

function bar()
    return 1, 2
end

local x       = bar() -- second return value gets discarded
local x, y    = bar()
local x, y, z = bar() - z gets assigned to `nil`

Many Lua functions also return a different number of arguments depending on a condition. For example, io.open returns a single value (the file handle) if it could open the file or two values (nil followed by an error message) if it could not.

Upvotes: 4

Related Questions