Python Director类中的Swig异常

时间:2019-04-03 07:14:49

标签: python c++ exception swig

我在Python中使用Swig Director包装了一些类。 我的每个类方法都返回一个MyError类。发生的事情是,一旦我从一个C ++派生了一个python类,而我忘记了返回MyError()对象,但我却没有返回“ pass”,或者我忘记了返回任何东西,则我的软件将在MyError的默认构造函数中崩溃通过读取访问冲突来上课,而我无法通过try / catch块跟踪此异常。

Swig处理此类情况的正确方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

Section 36.5.4 Exception unrolling在SWIG文档中:

  

通过Director将方法调用路由到Python,并将代理路由到C ++,异常处理是一个重要的问题。默认情况下,控制器将忽略在Python中解析的方法调用期间发生的异常。为了正确处理此类异常,有必要将它们临时转换为C ++异常。这可以通过%feature(“ director:except”)指令完成。在大多数情况下,以下代码就足够了:

%feature("director:except") {
    if ($error != NULL) {
        throw Swig::DirectorMethodException();
    }
}
  

此代码将在每次从导向器调用Python的方法后检查Python错误状态,并在发生错误时引发C ++异常。可以在C ++中捕获此异常以实现错误处理程序。目前在Swig :: DirectorMethodException对象中没有存储有关Python错误的信息,但是将来可能会改变。

     

可能是这样的情况:方法调用起源于Python,通过代理类升至C ++,然后通过Director方法返回Python。如果此时在Python中发生异常,那么该异常可以找到返回原始调用方的方式会很不错。这可以通过将普通的%exception指令与上面显示的Director:except处理程序结合使用来完成。这是一个合适的异常处理程序的示例:

%exception {
    try { $action }
    catch (Swig::DirectorException &e) { SWIG_fail; }
}
  

此示例中使用的Swig :: DirectorException类实际上是Swig :: DirectorMethodException的基类,因此它将捕获此异常。由于抛出Swig :: DirectorMethodException时仍会设置Python错误状态,因此C包装函数返回后,Python将立即注册异常。

示例

下面的示例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