Lua错误没有传递布尔值

时间:2010-07-11 17:28:57

标签: c api lua boolean-logic luac

这有效......

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。给出的变量在前一行中检索。我运行应用程序时遇到的错误是:

  

unprotected error to call in Lua API(script path...: Did not pass boolean to SetNoClip).

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

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

编辑:

SetNoClip 这个定义。

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,它将返回没有传递布尔值。我刚刚删除了布尔文字的错误检查,因为人们(包括我)通常依赖于不是布尔文字的参数被正确地视为布尔值。

3 个答案:

答案 0 :(得分:1)

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

or运算符返回其第一个参数(如果它被认为是真的),而第二个参数则返回。

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

  • A如果A的值为真,则
  • B如果B的值为false,A被视为false
  • C如果以上都不是

请注意,ABC不需要是实际的布尔值 - 只能将解释为的内容作为布尔值。由于nil被视为假值,因此第二种情况可能是您正在发生的,而传递给SetNoClip的参数是nil而不是true或{{ 1}}。

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

false

因为( otherObj ~= nil and otherObj:GetType() == "IceBlock" ) 运算符保证返回布尔值。

答案 1 :(得分: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;
}

答案 2 :(得分:0)

这取决于SetNoClip内部的内容(即,这不一定会导致问题)。但是,我很确定问题是andor会返回两边的值,而不是评估truefalse。换句话说,

foo and bar
如果foofoonil

将返回false,否则会返回bar

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