Python导演类中的Swig异常

问题描述 投票:1回答:1

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

Swig处理这种情况的正确方法是什么?

谢谢!

python c++ exception swig
1个回答
2
投票

SWIG文档中的Section 36.5.4 Exception unrolling

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

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

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

可能是方法调用源自Python,通过代理类传递到C ++,然后通过director方法返回到Python。如果此时Python中发生异常,那么找到返回原始调用者的异常会很好。这可以通过将普通%异常指令与director:上面显示的处理程序组合来完成。以下是合适的异常处理程序的示例:

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

此示例中使用的类Swig :: DirectorException实际上是Swig :: DirectorMethodException的基类,因此它将捕获此异常。因为抛出Swig :: DirectorMethodException时仍然设置了Python错误状态,所以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
© www.soinside.com 2019 - 2024. All rights reserved.