Обработка исключения C ++, созданного в функции, экспортируемой в 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
}

Это отлично работает в Windows ... но не работает в Linux - программа завершается следующим сообщением:

terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
  what():  N8Basilisk24InvalidArgumentExceptionE
Aborted

Я догадывался, что это произошло из-за того, что исключения поднялись до обработчика событий (поскольку механизм сценария использует сигналы для вызова функций в моих экспортированных классах), поэтому я повторно реализовал QApplication :: notify, чтобы обрабатывать там исключения, но они не были обнаружены.

Мой вопрос: делаю ли я что-то в корне неправильно? Кроме того, в качестве альтернативы, можно ли явно генерировать исключения сценария из моих классов C ++?

Заранее спасибо

РЕДАКТИРОВАТЬ: исправлено описание для включения оператора catch (...).

UPDATE ( РЕШЕНИЕ): Я «исправил» эту проблему, следуя стратегии, аналогичной той, что изложена в принятом ответе. Хотя я не выяснил, почему исключения не попадают в Linux (сейчас я подозреваю, что m_engine-> оценить порождает отдельный поток в 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 :: Assessment () вы можете проверить наличие неперехваченных исключений с помощью QScriptEngine :: hasUncaughtException () , получить объект ошибки с помощью uncaughtException ( ) , и теперь у вас есть сообщение, трассировка и номер строки в скрипте, где произошла ошибка!

Надеюсь, это кому-то поможет!

5
задан Alexander Kondratskiy 26 February 2011 в 04:31
поделиться