首页 文章

Lua错误没有传递布尔值

提问于
浏览
3

这有效......

if ( tileType == "water" or 
  ( otherObj and otherObj:GetType() == "IceBlock" )) then
  self:SetNoClip( true )
else
  self:SetNoClip( false )
end
  • 这些不......
self:SetNoClip( tileType == "water" or 
  ( otherObj and otherObj:GetType() == "IceBlock" ))

//----------------------------------------------------------

local noClip = ( tileType == "water" or 
  ( otherObj and otherObj:GetType == "IceBlock" ))
self:SetNoClip( noClip )

otherObj 测试只是评估otherObj是否为 nil . 给出的变量在前一行中检索 . 我运行应用程序时遇到的错误是:

在Lua API中调用的无保护错误(脚本路径...:未将布尔值传递给SetNoClip) .

SetNoClip是应用程序中的一个函数,它通过 lua_toboolean 获取推送到lua堆栈的参数 .

那么为什么第一次工作以及第二次和第三次返回错误呢?

编辑:

SetNoClip had 这个定义 .

int GameObject::LuaSetNoClip( lua_State *L ) {
  if ( !lua_isboolean( L, -1 )) {
    LogLuaErr( "Did not pass boolean to SetNoClip for GameObject: " + m_type );
    return luaL_error( L, "Did not pass boolean to SetNoClip" );
  }
  m_noClip = lua_toboolean( L, -1 );
  return 0;
}

问题是 lua_isboolean 不进行任何隐式类型转换(但 lua_toboolean 确实)并且只对文字布尔值返回true . 因此,如果它看到nil,它将返回一个布尔值没有't passed. I just removed the error check for a boolean literal, since people (including me) commonly rely on arguments that aren' t布尔文字被正确地视为布尔值 .

3 回答

  • 1

    如果该值被认为是非真值, and 运算符将返回其第一个参数,否则返回其第二个参数 .

    如果 or 运算符被认为是真的,则返回其第一个参数,否则返回其第二个参数 .

    因此, A or (B and C) 理论上可以返回以下任何一项:

    • A 如果 A 是一个被认为是真的值

    • B 如果 B 是一个被认为是假的值而 A 被认为是假的

    • C 如果以上都不是这种情况

    请注意, ABC 不需要是实际的布尔值 - 只能解释为布尔值 . 由于 nil 被认为是假值,因此第二种情况可能发生在您身上,而传递给 SetNoClip 的参数是 nil 而不是 truefalse .

    解决这个问题的一个选择是明确地与nil进行比较,而不仅仅是使用对象:

    ( otherObj ~= nil and otherObj:GetType() == "IceBlock" )
    

    因为 ~= 运算符保证返回一个布尔值 .

  • 1

    如您所见,任何对象都可以在Lua中使用布尔解释 . 因此,如果您希望传递一个布尔对象,那么LuaSetNoClip的实现不符合Lua的精神和实践 . 你应该直接使用 lua_toboolean .

    我认为你可以合理做的唯一参数检查是 luaL_checkany

    int GameObject::LuaSetNoClip( lua_State *L ) {
      luaL_checkany(L, 1);
      m_noClip = lua_toboolean( L, 1 );
      return 0;
    }
    
  • 0

    这取决于SetNoClip内部发生了什么(也就是说,这肯定是't necessarily cause problems in general). However, I',我确定问题是 andor 返回两边的值而不是评估为 truefalse . 换句话说,

    foo and bar
    

    如果 foonilfalse ,则返回 foo ,否则返回 bar .

    在您的情况下,原始代码将 truefalse 传递给SetNoClip,而在其他示例中,您要么传递 "water" ,要么将布尔值传递给SetNoClip . SetNoClip可能会阻塞字符串 .

相关问题