Раздел 36.5.4 Развертывание исключений в документации SWIG:
Поскольку директора направляют вызовы методов в Python и прокси-серверы направляют их в C ++, обработка исключений являетсяважное беспокойствоПо умолчанию директора игнорируют исключения, возникающие во время вызовов методов, которые разрешаются в Python.Чтобы правильно обрабатывать такие исключения, необходимо временно перевести их в исключения C ++.Это можно сделать с помощью директивы% feature ("Director: Кроме").В большинстве случаев будет достаточно следующего кода:
%feature("director:except") {
if ($error != NULL) {
throw Swig::DirectorMethodException();
}
}
Этот код будет проверять состояние ошибки Python после каждого вызова метода из директора в Python и генерировать исключение C ++ в случае ошибкипроизошло.Это исключение может быть перехвачено в C ++ для реализации обработчика ошибок.В настоящее время никакая информация об ошибке Python не сохраняется в объекте Swig :: DirectorMethodException, но это, вероятно, изменится в будущем.
Может случиться, что вызов метода происходит в Python, до C ++ проходит черезпрокси-класс, а затем обратно в Python через метод Director.Если в этот момент в Python возникает исключение, было бы хорошо, если бы это исключение вернулось к исходному вызывающему.Это можно сделать путем объединения обычной директивы% исключений с директором: кроме обработчика, показанного вышеВот пример подходящего обработчика исключений:
%exception {
try { $action }
catch (Swig::DirectorException &e) { SWIG_fail; }
}
Класс Swig :: DirectorException, используемый в этом примере, на самом деле является базовым классом Swig :: DirectorMethodException, поэтому он будет перехватыватьэто исключение.Поскольку состояние ошибки Python по-прежнему устанавливается при возникновении исключения Swig :: DirectorMethodException, Python зарегистрирует исключение, как только вернется функция оболочки C.
Пример
Вот пример test.i
, который иллюстрирует эту технику:
%module test
%module(directors="1") test
%feature("director");
%feature("director:except") {
if ($error != NULL) {
throw Swig::DirectorMethodException();
}
}
%exception {
try { $action }
catch (Swig::DirectorException &e) { SWIG_fail; }
}
%inline %{
class MyError {
int m_n;
public:
MyError(int n = 0) : m_n(n) {}
~MyError() {}
int get() const { return m_n; }
};
class Demo {
public:
Demo() {}
virtual ~Demo() {}
virtual MyError test() { return MyError(5); }
};
int func(Demo* d) { return d->test().get(); }
%}
После сборки и компиляции демонстрационная версия:
>>> import test
>>> d=test.Demo() # default class implementation
>>> test.func(d) # Call virtual method in a C++ test function.
5
Вышеописанное работало нормально.Ниже корректно переопределяется:
>>> class Demo2(test.Demo): # New class
... def test(self): # Override virtual function
... return 7 # But don't return a MyError object.
...
>>> d=Demo2()
>>> test.func(d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: SWIG director type mismatch in output value of type 'MyError'
Это перехватило исключение и вернуло полезное исключение.Ниже корректно переопределяет:
>>> class Demo2(test.Demo):
... def test(self):
... return test.MyError(7)
...
>>> d=Demo2()
>>> test.func(d)
7