Lua错误没有通过布尔值。

这个代码能够工作...

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

原文链接 https://stackoverflow.com/questions/3223989

点赞
stackoverflow用户161424
stackoverflow用户161424

这取决于 SetNoClip 内部发生了什么(即这不一定会导致一般问题)。但是,我相信问题在于 andor 返回两侧的值而不是评估为 truefalse。换句话说,

foo and bar

如果 foonilfalse,则将返回 foo,否则它将返回 bar

在你的情况下,原始代码将 truefalse 传递给 SetNoClip,而在其他示例中,你要么将 "water" 或布尔值传递给 SetNoClip。SetNoClip 可能无法处理字符串。

2010-07-11 17:49:00
stackoverflow用户148870
stackoverflow用户148870

and 操作符会返回它的第一个参数,如果那个值被认为是非真,否则返回它的第二个参数。

or 操作符会返回它的第一个参数,如果它被认为是真,否则返回它的第二个参数。

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

  • 如果 A 是被认为是真的值,那么返回 A
  • 如果 B 是被认为是假的值,且 A 被认为是假的值,那么返回 B
  • 如果不满足以上两个条件,那么返回 C

需要注意的是,ABC 不一定是实际的布尔值——只要它们可以被解释为布尔值即可。由于 nil 被认为是假的值,所以可能会发生第二种情况,传递给 SetNoClip 的参数是 nil 而不是 truefalse

解决这个问题的一种方法是显式地与 nil 进行比较,而不仅仅是使用对象:

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

因为 ~= 操作符保证返回一个布尔值。

2010-07-11 17:54:51
stackoverflow用户137317
stackoverflow用户137317

正如你所见,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;
}
2010-07-12 00:24:26