Я использую механизм сценариев 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 ( )
, и теперь у вас есть сообщение, трассировка и номер строки в скрипте, где произошла ошибка!
Надеюсь, это кому-то поможет!