Lua错误没有传递boolean
这有效...
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 有这个定义。
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,它将返回没有传递布尔值。我刚刚删除了布尔文字的错误检查,因为人们(包括我)通常依赖于不是布尔文字的参数被正确地视为布尔值。
This works...
if ( tileType == "water" or
( otherObj and otherObj:GetType() == "IceBlock" )) then
self:SetNoClip( true )
else
self:SetNoClip( false )
end
-
These don't...
self:SetNoClip( tileType == "water" or
( otherObj and otherObj:GetType() == "IceBlock" ))
//----------------------------------------------------------
local noClip = ( tileType == "water" or
( otherObj and otherObj:GetType == "IceBlock" ))
self:SetNoClip( noClip )
The otherObj
test just evaluates to whether otherObj is nil
or not. The variables given are retrieved in a previous line. The error I get when the application runs is:
unprotected error to call in Lua API(script path...: Did not pass boolean to SetNoClip).
SetNoClip is a function in the application that grabs the argument pushed onto the lua stack via lua_toboolean
.
So why does the first work and the second and third return errors?
EDIT:
SetNoClip had this definition.
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;
}
The problem is that lua_isboolean
doesn't do any implicit type conversion (but lua_toboolean
does) and will only return true for literal boolean values. So if it sees nil, it will return that a boolean wasn't passed. I just removed the error check for a boolean literal, since people (including me) commonly rely on arguments that aren't boolean literals being treated correctly as booleans.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果该值被视为非 true,则
and
运算符返回其第一个参数,否则返回其第二个参数。如果被认为是 true,则
or
运算符返回其第一个参数,否则返回其第二个参数。因此,
A 或(B 和 C)
理论上可以返回以下任意值:A
如果A
被认为是 true 值B
如果B
是一个被视为 false 的值,并且A
被视为 falseC
如果上述情况均不是,请注意
A
、B
和C
不需要是实际的布尔值 - 只是可以解释为布尔值的值。由于nil
被视为假值,因此您可能会遇到第二种情况,并且传递给SetNoClip
的参数是nil
true
或false
。解决此问题的一种选择是显式与 nil 进行比较,而不是仅使用对象:
因为
~=
运算符保证返回布尔值。The
and
operator returns its first argument if that value is something considered non-true, and its second argument otherwise.The
or
operator returns its first argument if it is something considered true, and its second argument otherwise.Thus,
A or (B and C)
can theoretically return any of the following:A
ifA
is a value considered trueB
ifB
is a value considered false andA
is considered falseC
if neither of the above is the caseNote that
A
,B
, andC
are not required to be actual boolean values - only things that can be interpreted as booleans. Sincenil
is considered a false value, it's possible that the second case is occurring for you, and the argument being passed toSetNoClip
isnil
instead oftrue
orfalse
.One option to fix this would be to explicitly compare with nil, instead of just using the object:
since the
~=
operator is guaranteed to return a boolean.正如您所看到的,在 Lua 中任何对象都可以有布尔解释。因此,您的 LuaSetNoClip 实现并不符合其精神。如果您希望只传递一个布尔对象,请使用 Lua 的实践。您应该直接使用
lua_toboolean
。我认为您可以合理执行的唯一参数检查是 luaL_checkany :
As you have seen, any object can have a boolean interpretation in Lua. Because of this, your implementation of LuaSetNoClip is not true to the spirit & practice of Lua if you expect just a boolean object to be passed. You should use
lua_toboolean
directly.I think the only argument check you can reasonably do is
luaL_checkany
:这取决于 SetNoClip 内部发生的情况(即,这通常不一定会导致问题)。但是,我很确定问题是
and
和or
返回两侧的值,而不是评估为true
或假
。换句话说,如果
foo
为nil
或false
,则返回foo
,否则返回栏
。在您的情况下,原始代码将
true
或false
传递给 SetNoClip,而在其他示例中,您要么传递"water"
,要么传递布尔值设置为 SetNoClip。 SetNoClip 可能被绳子卡住了。It depends on what goes on inside SetNoClip (i.e. this won't necessarily cause problems in general). However, I'm pretty sure the problem is that
and
andor
return the values on either side rather than evaluating totrue
orfalse
. In other words,will return
foo
iffoo
is eithernil
orfalse
, otherwise it will returnbar
.In your case, the original code passes
true
orfalse
to SetNoClip whereas in the other examples you're either passing"water"
, or a boolean to SetNoClip. SetNoClip might be choking on the string.