处理导出到QtScript的函数中抛出的C++异常

Ale*_*kiy 5 c++ qt exception qtscript

我在我的应用程序中使用Qt脚本引擎作为用户访问其功能的替代方法.因此,我将一些C++类导出到Qt ScriptEngine,它将作为应用程序的接口.问题是,这些C++类可以抛出异常.

我有一个"ScriptInterface"类在自己的线程上运行,侦听处理脚本的请求.因此,当我评估用户的脚本时,我有一个try/catch块来处理异常,并将错误打印到应用程序中的控制台.

...
try {
   m_engine->evaluate(script, name);
}
catch (Exception const& e) {
   // deal with it
}
catch (...) {
   // scary message
}
Run Code Online (Sandbox Code Playgroud)

这在windows中完美运行...但在linux中不起作用 - 程序终止于此消息:

terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
  what():  N8Basilisk24InvalidArgumentExceptionE
Aborted
Run Code Online (Sandbox Code Playgroud)

我有一种预感,因为异常冒泡到事件处理程序(因为脚本引擎使用信号来调用导出的类中的函数),所以我重新实现了QApplication :: notify,以处理那里的异常,但它们不是'抓住了.

我的问题是,我做了一些根本错误的事情吗?另外,作为替代方案,是否可以从我的C++类中显式抛出脚本异常?

提前致谢

编辑:修改说明以包含catch(...)语句.

更新(解决方案):我通过遵循类似于接受的答案中概述的策略来"修复"此问题.虽然我还没有找到为什么异常不会被linux捕获的原因(我现在怀疑是m_engine-> evaluate在linux上产生一个单独的线程),但我已经开始使用预期的异常抛出方式在Qt Scripts中,就是这样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);
}
Run Code Online (Sandbox Code Playgroud)

现在是这样的:(特别注意返回类型)

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();
}
Run Code Online (Sandbox Code Playgroud)

那么在哪里处理这些脚本错误呢?在调用QScriptEngine::evaluate()你之后可以检查是否有任何未捕获的异常,用QScriptEngine::hasUncaughtException(),获取错误对象uncaughtException(),现在你在错误发生的脚本中有消息,跟踪和行号!

希望这可以帮助别人!

whe*_*ies 3

当我尝试使用 SWIG 和 Python 来包装 C++ 库时,我遇到了类似的问题。最终发生的事情是,我为所有包装的类创建了一个存根,这些类捕获了异常并静静地失败了。幸运的是,我拥有只传递容器类和状态模式对象的包装功能,因此我可以轻松检查是否有问题。我可以给你同样的建议吗?

  1. 用另一个函数包装你想要的函数,除了返回值之外,接口相同。
  2. 创建一个对象,该对象不仅包含请求的返回类型,还包含错误指示符。
  3. 让脚本确保检查异常。

是的,如果您授予脚本引擎访问异常工厂(一个唯一目的是抛出 C++ 异常的类)的权限,脚本引擎很可能会抛出 C++ 异常。