2014-09-03 86 views
1

这里是一个非常简单的C函数:SWIG:如何根据原始返回值对返回值进行键入映射?

bool GetSomething(string* result) 

调用该函数后,返回的值应指示如果result拥有所需要的信息,并且用户可以检查返回值相应地处理。

痛饮此功能在Python代码中使用,我用的是默认的typemaps.i文件,然后改变了功能

bool GetSomething(string* OUTPUT) 

这工作,但仍然繁琐。我不得不这样做是为了得到我想要的结果:

success, result = GetSomething() 
if success: 
    # handle result 
else: 
    # throw exception 

理想情况下,我想有这样的接口,而不是:

result = GetSomething() 
if result: 
    # handle result 

任何帮助,将不胜感激。

+0

你为什么不抛出一个异常,如果函数失败,所以你可以使用'string GetSomething()'。 – MasterMind 2014-09-04 15:20:47

+0

@MasterMind这是一个免费的C++代码库,我不允许修改。 – yegle 2014-09-04 15:35:14

+0

您不必在C++中抛出异常,就在SWIG包装器中,因此它变成了Python异常。 – 2014-09-05 02:33:54

回答

3

下面是评论中提到的想法的示例.i文件。将成功的返回状态转换为None并将失败的返回状态转换为Python中的异常,并将输出参数附加到返回值。这不需要更改C++代码库:

%module x 

%include <exception.i> 

// convert non-zero int return values to exceptions 
%typemap(out) int %{ 
    if($1) 
     SWIG_exception(SWIG_RuntimeError,"non-zero return value"); 
    $result = Py_None; 
    Py_INCREF(Py_None); // Py_None is a singleton so increment its reference if used. 
%} 

// Easy way for int*, but customize below for more complicated types 
// %apply int* OUTPUT {int*}; 

// suppress the output parameter as an input. 
%typemap(in,numinputs=0) int* (int tmp) %{ 
    $1 = &tmp; 
%} 

// append int* output parameters to the return value. 
%typemap(argout) int* { 
    PyObject* tmp = PyLong_FromLong(*$1); 
    $result = SWIG_Python_AppendOutput($result,tmp); 
} 

// %inline declares and exposes a function 
%inline %{ 
    int func(int val, int* pOut) 
    { 
     if(val < 1) 
      return 1; 
     *pOut = 2 * val; 
     return 0; 
    } 
%} 

如果SWIG这样。我跟swig -python -c++ x.i,结果编译成一个Python扩展:

>>> import x 
>>> x.func(2) 
4 
>>> x.func(0) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: non-zero return value 
0

我目前的破解,希望这可以帮助某人。

%{ 
#define GetSomething 1 
%} 

%typemap(out) bool %{ 
#if $symname == 1 
if (result) { 
return Py_FromString(arg0->data()); 
} else { 
return Py_None; 
} 
#endif 
%}