Не могу поймать исключение! - PullRequest
4 голосов
/ 27 мая 2009

Я использую swig для переноса класса из библиотеки C ++ с помощью python. В целом, это работает, но есть исключение, которое выдается из библиотеки, и я не могу поймать его в интерфейсе swig, поэтому он просто вылетает из приложения python!

Класс PyMonitor.cc описывает интерфейс swig для нужного класса Monitor. Конструктор монитора выдает исключение, если не удается подключиться. Я хотел бы обработать это исключение в PyMonitor, например ::100100

PyMonitor.cc:

#include "Monitor.h"  

// ...  

bool PyMonitor::connect() {  
    try {  
        _monitor = new Monitor(_host, _calibration);  
    } catch (...) {  
        printf("oops!\n");  
    }  
}

// ...

Тем не менее, метод connect () никогда не перехватывает исключение, я просто получаю сообщение об ошибке «terminate вызывает после throwing ...», и программа прерывается.

Я не слишком много знаю о swig, но мне кажется, что это все в порядке в C ++, и исключение должно распространяться на метод connect () перед уничтожением программы.

Есть мысли?

Ответы [ 3 ]

4 голосов
/ 16 сентября 2011

Вы должны переслать исключения в Python, если вы хотите проанализировать их там. См. Документацию SWIG . Чтобы пересылать исключения, вам нужно всего лишь добавить некоторый код в файл интерфейса SWIG (.i). По сути, это может быть где угодно в файле .i.

Здесь должны быть указаны все типы исключений, и SWIG только перехватывает перечисленные типы исключений (в данном случае std :: runtime_error, std :: invalid_argument, std :: out_of_range), все остальные исключения пойманы как неизвестные исключения (и, следовательно, перенаправлены правильно!).

// Handle standard exceptions.
// NOTE: needs to be before the %import!
%include "exception.i"
%exception
{
 try
 {
   $action
 }
 catch (const std::runtime_error& e) {
   SWIG_exception(SWIG_RuntimeError, e.what());
 } 
 catch (const std::invalid_argument& e) {
   SWIG_exception(SWIG_ValueError, e.what());
 }
 catch (const std::out_of_range& e) {
   SWIG_exception(SWIG_IndexError, e.what());
 }
 catch (...) { 
   SWIG_exception(SWIG_RuntimeError, "unknown exception");
 } 
}
1 голос
/ 28 мая 2009

Возможно, что функция, вызванная монитором прямо или косвенно constructor, нарушает спецификацию исключений и не позволяет выбрасывать std::bad_exception. Если вы не заменили стандартную функцию для захвата этого, то это объяснило бы поведение, которое вы видите.

Чтобы проверить эту гипотезу, вы можете попытаться определить свой собственный обработчик:

void my_unexpected()
{
    std::cerr << "Bad things have happened!\n";
    std::terminate();
}


bool PyMonitor::connect() {  

    std::set_unexpected( my_unexpected );

    try {  
        _monitor = new Monitor(_host, _calibration);  
    } catch (...) {  
        printf("oops!\n");  
    }  
}

Если вы получаете "Плохие вещи произошли!" сообщение об ошибке, то вы подтвердили, что это так, но, к сожалению, не так много, что вы можете сделать. Если вам «повезло», вы можете создать исключение из my_unexpected, которое разрешено спецификацией исключений для функции, которая в данный момент не работает, но в любом случае ваш неожиданный обработчик не может нормально завершиться. Он должен бросить или иным образом прекратить.

Чтобы исправить это, вам действительно нужно войти в вызываемый код и либо исправить его, чтобы спецификация исключений не нарушалась, либо путем исправления самой спецификации, либо путем исправления кода, чтобы он не генерировал исключение, которое не не ожидал.

Другая возможность заключается в том, что во время разматывания стека создается исключение, вызванное исходным исключением. Это также может привести к прекращению процесса. В этом случае, хотя вы можете заменить стандартную функцию завершения, у вас нет выбора, кроме как прервать программу. Обработчику завершения запрещается выбрасывать или возвращать, он должен завершать программу.

1 голос
/ 27 мая 2009

Я не знаком с swig или с совместным использованием C ++ и Python, но если это относится к последней версии Microsoft Visual C ++, то класс Monitor, вероятно, генерирует структурированное исключение C, а не C ++ Типизированное исключение. Структурированные исключения C не обрабатываются обработчиками исключений C ++, даже catch(...) one.

Если это так, вы можете использовать ключевые слова __try/__except (вместо try/catch) или использовать функцию _set_se_translator для преобразования структурированного исключения C в типизированное исключение C ++.

(Старые версии MSVC ++ рассматривали структурированные исключения C как типы C ++ int, а перехватываются обработчиками C ++, если я правильно помню.)

Если это не в Microsoft Visual C ++, тогда я не уверен, как это могло произойти.

РЕДАКТИРОВАТЬ: Поскольку вы говорите, что это не MSVC, возможно, что-то еще перехватывает исключение (и завершает программу) до того, как ваш код его получает, или, может быть, в вашем блоке catch есть что-то, что вызывает другое исключение? Если не вдаваться в подробности, это единственные случаи, которые могут привести к появлению этих симптомов.

...