【发布时间】:2016-07-01 13:52:55
【问题描述】:
我正在包装以下 C++ 代码:
// content of cpp.h
class A
{
public:
virtual int fnA() = 0;
virtual ~A() { }
};
class B
{
public:
int fnB(A &a)
{
return a.fnA();
}
};
由 SWIG 使用 SWIG 包装器:
// content of swigmodule.i
%module(directors="1") swigmodule
%feature("director");
%feature("director:except") {
if ($error != NULL) {
fprintf(stderr, "throw\n");
throw Swig::DirectorMethodException();
}
}
%exception {
try { $action }
catch (Swig::DirectorException &e) { fprintf(stderr, "catch\n"); SWIG_fail; }
}
%{
#include "cpp.h"
%}
%include "cpp.h"
异常处理是从 SWIG 手册中复制的。 使用它,我生成了 SWIG 包装器: “痛饮 -c++ -python swigmodule.i; g++ -shared -fPIC -I/usr/include/python2.7 swigmodule_wrap.cxx -o _swigmodule.so"
在 Python 中使用“void fnA()”错误地重载“int fnA()”函数时会出现问题。
# content of useit.py
from swigmodule import A, B
class myA(A):
def fnA(self):
print("myA::fnA")
b = B();
a = myA();
print("%d"% b.fnB(a) )
生成的 SWIG 包装器在运行时正确地将其标记为错误; fnA(self) 返回不是 int 的 None。但是,控制台的输出是:
$ python useit.py
myA::fnA
catch
Traceback (most recent call last):
File "useit.py", line 12, in <module>
print("%d"% b.fnB(a) )
File "/home/schuttek/tmp/swigmodule.py", line 109, in fnB
def fnB(self, *args): return _swigmodule.B_fnB(self, *args)
TypeError: SWIG director type mismatch in output value of type 'int'
这是一种误导,因为它表明错误在 B::fnB 中,而实际错误在重载 A::fnA 中。
如何让 SWIG 对发生错误的位置提供有意义的诊断?在我的真实代码(这是一个简化版本)中,我不得不使用 GDB 来捕获 Swig::DirectorException 类的构造函数。这是不需要的,因为实际错误在 Python 域中(执行了不正确的重载),我想保护未来的 Python 用户免受 GDB 及其使用以及 SWIG 内部(如 DirectorException)的影响。
【问题讨论】:
-
我不确定这是否真的是 A 中的错误,它是在应用
fnB期间检测到类型不匹配并且正确的。如果你真的想要的话,你可能可以对元类做一些聪明的事情来更早地发现它,但我不确定我是否将它作为“一件大事”来购买。 -
我希望的是,TypeError 中的文本在其当前诊断中添加了“在匹配 A::fnA 期间”之类的内容。
-
要全局更改吗?我可以告诉你哪个类型映射控制
%typemap(directorout),使用宏%dirout_fail来实际执行它,但是全局更改很棘手,因为已经有很多类型映射用于导演,所以这不仅仅是调整一个的情况适用于任何地方。申请所有int或任何其他已知的返回类型应该足够简单。 -
我想我希望在全球范围内进行更改。非常感谢您提供示例类型图!