我在我的应用程序中使用 Qt 脚本引擎作为用户访问其功能的替代方式。因此,我将一些 C++ 类导出到 Qt ScriptEngine,它将作为应用程序的接口。问题是,这些 C++ 类可以抛出异常。
我有一个在自己的线程上运行的“ScriptInterface”类,监听处理脚本的请求。因此,当我评估用户的脚本时,我在它周围有一个 try/catch 块来处理异常,并将错误打印到应用程序的控制台。
...
try {
m_engine->evaluate(script, name);
}
catch (Exception const& e) {
// deal with it
}
catch (...) {
// scary message
}
这在 Windows 中完美运行......但在 linux 中不起作用 - 程序以以下消息终止:
terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
what(): N8Basilisk24InvalidArgumentExceptionE
Aborted
我有一种预感,这是因为异常冒泡到事件处理程序(因为脚本引擎使用信号来调用我导出的类中的函数),所以我重新实现了 QApplication::notify,以在那里处理异常,但它们不是没有抓住。
我的问题是,我在做一些根本错误的事情吗?此外,作为替代方案,是否可以从我的 C++ 类中显式抛出脚本异常?
提前致谢
编辑:修复了描述以包含 catch(...) 语句。
更新(解决方案):我通过遵循类似于已接受答案中概述的策略来“解决”这个问题。虽然我还没有找到为什么异常不会在 linux 上被捕获的根源(我现在怀疑是 m_engine->evaluate 在 linux 上生成一个单独的线程),但我已经开始使用预期的异常抛出方式在 Qt 脚本中,即QScriptContext::throwError()
.
在我的函数看起来像这样的情况下:(随机示例)
void SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
throw InvalidArgumentException(
"Not the answer to Life, the Universe and Everything.");
}
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
}
现在是这样的:(特别注意返回类型)
QScriptValue SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
// assuming m_engine points to an instance of
// QScriptEngine that will be calling this function
return m_engine->currentContext()->throwError(QScriptContext::SyntaxError,
"Not the answer to Life, the Universe and Everything.");
}
try {
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
} catch (ExpectedException const& e) {
return m_engine->currentContext()->throwError(QScriptContext::UnknownError,
e.message());
}
// if no errors returned, return an invalid QScriptValue,
// equivalent to void
return QScriptValue();
}
那么在哪里处理这些脚本错误呢?调用后QScriptEngine::evaluate()
可以查看是否有未捕获的异常,用QScriptEngine::hasUncaughtException()
,用 获取错误对象uncaughtException()
,现在脚本中出现错误的消息、trace、行号就知道了!
希望这可以帮助某人!