2014-09-03 69 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 
%}