我使用SWIG将C lib包装到python模块。但似乎没有在正确的地方引发异常,我有一个简单的演示,
except_test.i
%module except_test
%{
#include "except_test.h"
#include <stdio.h>
%}
%{
static int flagged_exception = 0;
void throw_except()
{
flagged_exception = 1;
printf("flag set \n");
}
%}
%exception {
$action
printf("exception block\n");
if (flagged_exception) {
printf("before setstring\n");
PyErr_SetString(PyExc_RuntimeError, "test except");
printf("after setstring\n");
flagged_exception = 0;
}
}
%include "except_test.h"
except_test.c
#include "except_test.h"
int except_test(int a) {
if (a < 0) {
throw_except();
return 0;
} else{
return -1;
}
}
run_except.py
from except_test import *
import time
def test():
b = except_test(-1)
print 'b=', b
try:
test()
except:
print "caught exception"
for i in range(10):
print i
time.sleep(1)
现在如果我运行run_except.py
$python run_except.py
flag set
exception block
before setstring
after setstring
b= 0
0
Traceback (most recent call last):
File "run_except.py", line 15, in <module>
time.sleep(1)
RuntimeError: test except
如输出所示,try / catch块没有捕获异常。 为什么是这样?以及如何避免这种情况?
谢谢,
答案 0 :(得分:3)
您必须从Python扩展程序返回NULL
才能立即注意到错误:
if (flagged_exception) {
PyErr_SetString(PyExc_RuntimeError, "test except");
flagged_exception = 0;
return NULL;
}
但是使用通用SWIG宏将使SWIG接口更易于移植到其他语言。
答案 1 :(得分:2)
您需要在SWIG_fail;
之后立即PyErr_SetString
。或者,有一个方便的(以及更重要的与语言无关的)宏SWIG_exception(SWIG_RuntimeError, "error message")
包裹PyErr_SetString
和SWIG_fail
。