我尝试使用C ++来包装一些简单的C ++,并在尝试包装最基本的东西时遇到问题。
SWIG似乎没有尝试在类型映射中尝试捕获和异常。
例如,对于以下SIWG接口文件:
%module badswig
std::string func();
SWIG生成此:
SWIGINTERN PyObject *_wrap_func(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
std::string result;
if (!PyArg_ParseTuple(args,(char *)":func")) SWIG_fail;
result = func();
resultobj = SWIG_NewPointerObj((new std::string(static_cast< const std::string& >(result))), SWIGTYPE_p_std__string, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
return NULL;
}
请注意,new std::string
完全不受保护,因此如果std::bad_alloc
将被抛出,它将传播到Python并崩溃。
可能还有其他案例,不仅SWIG使用new
。
有%exception
为包装函数处理此问题(如果func()
抛出),但我找不到任何可以处理这种情况的字体图,特别是SWIG提供的字体。
我错过了什么吗?有没有正确处理这个?
修改
在回答答案并澄清我的问题时,%exception
没有达到我的要求:
%module badswig
%exception %{
try {
$action
} catch (const std::bad_alloc&) {
PyErr_NoMemory();
SWIG_fail;
}
%}
std::string func();
生成这个:
SWIGINTERN PyObject *_wrap_func(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
std::string result;
if (!PyArg_ParseTuple(args,(char *)":func")) SWIG_fail;
try {
result = func();
} catch (const std::bad_alloc&) {
PyErr_NoMemory();
SWIG_fail;
}
resultobj = SWIG_NewPointerObj((new std::string(static_cast< const std::string& >(result))), SWIGTYPE_p_std__string, SWIG_POINTER_OWN | 0 );
return resultobj;
fail:
return NULL;
}
注意new std::string
没有尝试捕捉它。
答案 0 :(得分:0)
typemap只是告诉SWIG要生成什么接口代码来转换调用参数和返回函数的值。 %exception
在要包装的函数之前和之后立即生成代码,将异常从C ++转换为目标语言或将C ++异常转换为目标语言等效项。如果你按照SWIG文档使用%exception
,你会发现你的包装函数包含你为该函数指定的类型映射代码,以及围绕你的C ++函数的异常代码:
void swig_function(PyObj*) {
typemap-related code to convert args from Python to C++
exception-related code
your-c++-func(args)
exception-related code (catch clauses etc)
typemap-related code to convert return value from C++ to Python
}