【问题标题】:Determine the signature of a Lua function from the C API从 C API 确定 Lua 函数的签名
【发布时间】:2017-01-12 02:51:48
【问题描述】:

我正在开发的框架可以使用 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 中执行此操作。

【问题讨论】:

    标签: c lua


    【解决方案1】:

    你不能那样做。每个 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 后跟错误消息)。

    【讨论】:

    • 似乎仍然可以解析 luac 输出以获取函数的参数计数。
    • 而且一个函数可以有0个或多个return语句,即使是同一个return语句,每次也可以返回不同数量的值。
    • @Vlad 谢谢你提到这一点。在阅读了有关该主题的更多内容后,似乎可以对字节码进行我们想做的那种分析。
    猜你喜欢
    • 2010-09-13
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 2015-08-09
    • 1970-01-01
    相关资源
    最近更新 更多