从C API确定Lua函数的签名

时间:2016-09-04 15:40:27

标签: c lua

我正在研究的框架可以使用Lua模块进行扩展。每个模块的Lua源代码都是使用我们的编译器编译的,该编译器基于官方的Lua解释器,然后保存为字节码。这些模块必须满足某些要求:

-- 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

如果在将Lua源编译到模块中时可以检查要求,那将是很好的。这会让生活更轻松:

  • 对于那些编写模块的人,因为他们会被告知他们犯了哪些错误;和
  • 对我们来说,因为我们可以假设模块是正确的(正如假设已安装的资源,如图标是正确的),因此不必在运行时实现任何检查。

检查特定值是否属于某种类型并不困难:

// 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!
}

但是如何检查一个函数是否需要一定数量的参数并返回一个包含某些字段的表呢?

-- 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

请注意,我问这是否可能(以及如果是这样,如何)使用C API,这与this question不同,后者是在Lua中执行此操作。

1 个答案:

答案 0 :(得分:4)

你做不到。每个Lua函数都可以使用任意数量的参数并返回任意类型的任意数量的值。

我认为你能做的最好的事情是在某处写一个显式类型注释(在注释中或在运行时出现的东西),然后检查它。还有Typed Lua,这是一个具有静态类型系统的实验性Lua方言。

例如函数如何接收任意数量的参数,如果函数接收的参数少于参数,则额外参数将分配给nil。如果传递的参数多于函数作为参数的参数,则会丢弃额外的参数。

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

缺少参数nil也常用于实现带有可选参数的函数,这意味着检查参数数量的天真尝试将与这个常见的Lua习语冲突:

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

返回参数也很灵活,就像输入参数是:

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`

许多Lua函数也会根据条件返回不同数量的参数。例如,io.open返回单个值(文件句柄),如果它可以打开文件或两个值(nil后跟错误消息),如果它不能。