澄清(抱歉问题不具体):他们都试图将堆栈上的项目转换为lua_Number
. lua_tonumber
还将转换代表数字的字符串。如何luaL_checknumber
处理不是数字的东西?
还有luaL_checklong
和luaL_checkinteger
。它们与(int)luaL_checknumber
和(long)luaL_checknumber
分别相同吗?
澄清(抱歉问题不具体):他们都试图将堆栈上的项目转换为lua_Number
. lua_tonumber
还将转换代表数字的字符串。如何luaL_checknumber
处理不是数字的东西?
还有luaL_checklong
和luaL_checkinteger
。它们与(int)luaL_checknumber
和(long)luaL_checknumber
分别相同吗?
参考手册确实回答了这个问题。我引用了 Lua 5.2 参考手册,但在 5.1 手册中也可以找到类似的文本。但是,该手册非常简洁。很少有任何一个事实在一个以上的句子中被重述。此外,您经常需要关联分散在很远的部分中陈述的事实,以了解 API 函数的更深层次的含义。
这不是缺陷,而是设计使然。这是该语言的参考手册,因此其主要目标是完整(和正确)描述该语言。
有关“如何”和“为什么”的更多信息,一般建议是同时阅读《Lua 编程》。描述 Lua 5.0 的在线副本变得相当长。当前的纸质版本描述了 Lua 5.1,描述 Lua 5.2 的新版本正在制作中。也就是说,即使第一版也是一个很好的资源,只要您还注意自 5.0 版以来该语言的变化。
luaL_check*
参考手册对函数系列有相当多的说明。
每个 API 条目的文档块都附有一个标记,该标记描述了它对堆栈的使用,以及在什么条件下(如果有)它会抛出错误。这些令牌在第 4.8 节中进行了描述:
每个函数都有一个这样的指标:
[-o, +p, x]
第一个字段 o 是函数从堆栈中弹出的元素数量。第二个字段 p 是函数压入堆栈的元素数量。(任何函数总是在弹出其参数后推送其结果。) x|y 形式的字段表示该函数可以推送(或弹出)x 或 y 元素,具体取决于具体情况;一个问号“?” 意味着我们无法通过仅查看它的参数来知道函数弹出/推送多少元素(例如,它们可能取决于堆栈上的内容)。第三个字段 x 表示函数是否会抛出错误:'-' 表示函数永远不会抛出任何错误;'e' 表示函数可能会抛出错误;'v' 表示该函数可能会故意抛出错误。
在第 5 章的开头,它记录了整个辅助库(官方 API 中的所有函数,其名称以luaL_
而不只是开头lua_
)我们发现:
辅助库中的几个函数用于检查 C 函数参数。因为错误消息是针对参数格式化的(例如,“bad argument #1”),所以您不应该将这些函数用于其他堆栈值。
如果检查不满足,调用 luaL_check* 的函数总是抛出错误。
该函数luaL_checknumber
使用令牌记录,[-0,+0,v]
这意味着它不会干扰堆栈(它不会弹出任何内容,也不会推送任何内容)并且它可能会故意抛出错误。
具有更具体数字类型的其他函数主要在函数签名上有所不同。所有的描述都类似于luaL_checkint()
“检查函数参数arg
是否为数字并将此数字强制转换为int
”,并根据需要更改强制转换中命名的类型。
该函数lua_tonumber()
使用标记进行描述,这[-0,+0,-]
意味着它对堆栈没有影响并且不会引发任何错误。它记录了从指定的堆栈索引返回数值,如果堆栈索引不包含足够数字的内容,则返回 0。记录使用更通用的函数lua_tonumberx()
,该函数还提供一个标志,指示它是否成功转换了一个数字。
它也有以更具体的数字类型命名的兄弟姐妹,它们执行所有相同的转换,但转换它们的结果。
最后,人们也可以参考源代码,理解手册是按照它的意图描述语言,而源代码是该语言的特定实现,可能有错误,或者可能揭示实现细节在未来的版本中可能会发生变化。
的来源luaL_checknumber()
在lauxlib.c
. 可以看出,它是根据调用lua_tonumberx()
的内部函数来实现的,该函数是用来实际抛出格式化的错误消息的。tagerror()
typerror()
luaL_argerror()
他们都尝试将堆栈上的项目转换为 lua_Number。lua_tonumber 也会转换代表数字的字符串。luaL_checknumber 在转换失败时会引发 (Lua) 错误 - 它会长跳转并且永远不会从 C 函数的 POV 返回。lua_tonumber 只返回 0(这也可以是一个有效的返回值。)所以你可以编写这个代码,它应该比首先检查 lua_isnumber 更快。
double r = lua_tonumber(_L, idx);
if (r == 0 && !lua_isnumber(_L, idx))
{
// Error handling code
}
return r;