luaL_checknumber和lua_tonumber有什么区别?

时间:2012-08-22 17:32:16

标签: lua

澄清(抱歉问题不具体):他们都试图将堆栈上的项目转换为lua_Numberlua_tonumber还将转换表示数字的字符串。 luaL_checknumber如何处理不是数字的东西?

还有luaL_checklongluaL_checkinteger。它们分别与(int)luaL_checknumber(long)luaL_checknumber相同吗?

2 个答案:

答案 0 :(得分:10)

参考手册确实回答了这个问题。我引用了Lua 5.2参考手册,但同样的文字也在5.1手册中找到。但是,手册非常简洁。任何单一事实很难在一个以上的句子中重述。此外,您经常需要关联广泛分离的部分中陈述的事实,以了解API函数的深层含义。

这不是缺陷,而是设计上的。这是该语言的参考手册,因此其主要目标是完全(和正确)描述该语言。

有关"如何"的更多信息和"为什么"一般的建议是阅读Programming in Lua。由于它描述了Lua 5.0,因此在线版本的版本相当长。目前的纸质版本描述了Lua 5.1,并且正在编写一个描述Lua 5.2的新版本。也就是说,即使是第一版也是一个很好的资源,只要你也注意自5.0版本以来语言的变化。

参考手册对于luaL_check*函数系列有相当多的说法。

每个API条目的文档块都附带一个描述其堆栈使用的标记,并在什么条件下(如果有的话)会引发错误。这些令牌在section 4.8

中描述
  

每个函数都有一个如下指示符:[-o, +p, x]

     

第一个字段o是函数弹出的元素数量   堆。第二个字段p是函数推送的元素数量   到堆栈上。 (任何功能总是在弹出后推送其结果   它的参数。)x | y形式的字段表示函数可以推送   (或弹出)x或y元素,视情况而定;审讯   标记'?'意味着我们无法知道这个功能有多少元素   通过仅查看其参数来弹出/推动(例如,它们可能依赖于   什么在堆栈上)。第三个字段x告诉函数是否正常   可能会抛出错误:' - '意味着函数永远不会抛出任何错误; ' E'   意味着该函数可能会抛出错误; ' V'意味着该功能可能会抛出   故意错误。

在第5章的头部,它记录了整个辅助库(官方API中的所有函数,其名称以luaL_开头,而不仅仅是lua_),我们发现:

  

辅助库中的几个函数用于检查C.   函数参数。因为错误消息的格式为   参数(例如,"错误的参数#1和#34;),你不应该使用这些   其他堆栈值的函数。

     

如果检查不是,则称为luaL_check *的函数总是抛出错误   满意。

函数luaL_checknumber记录了令牌[-0,+0,v],这意味着它不会打扰堆栈(它不会弹出任何内容并且什么也不推送),并且可能故意抛出错误。

具有更多特定数字类型的其他函数主要在函数签名中有所不同。所有内容都与luaL_checkint()&#34类似地进行描述;检查函数参数arg是否为数字并将此数字转换为int",改变在lua_tonumber()中指定的类型适当地施放。

使用令牌[-0,+0,-]描述函数lua_tonumberx(),这意味着它对堆栈没有影响,并且不会抛出任何错误。记录为从指定的堆栈索引返回数值,如果堆栈索引不包含足够数字的值,则返回0。记录使用更通用的函数lauxlib.c,它还提供一个标志,指示它是否成功转换了数字。

它也有以更具体的数字类型命名的兄弟姐妹,这些数字类型执行所有相同的转换但是转换结果。

最后,还可以参考源代码,并理解手册是按照预期描述语言,而源是该语言的特定实现,可能有错误,或者可能揭示实现在未来版本中可能会更改的详细信息。

luaL_checknumber()的来源位于lua_tonumberx()。可以看出,它是以tagerror()和内部函数typerror()实现的,它调用{{1}}实现了luaL_argerror()以实际抛出格式化的错误消息。

答案 1 :(得分:1)

他们都试图将堆栈上的项目转换为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;