SWIG:如何根据原始返回值对返回值进行类型映射?

yeg*_*gle 2 swig

这是一个非常简单的 C 函数:

bool GetSomething(string* result)
Run Code Online (Sandbox Code Playgroud)

调用该函数后,返回值应指明是否result保存了需要的信息,用户可以查看返回值进行相应处理。

为了在 Python 代码中使用 SWIG 这个函数,我使用默认typemaps.i文件,然后将该函数更改为

bool GetSomething(string* OUTPUT)
Run Code Online (Sandbox Code Playgroud)

这有效,但仍然很麻烦。我必须这样做才能得到我想要的结果:

success, result = GetSomething()
if success:
    # handle result
else:
    # throw exception
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想要这个界面:

result = GetSomething()
if result:
    # handle result
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激。

Mar*_*nen 5

这是评论中提到的想法的示例 .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;
    }
%}
Run Code Online (Sandbox Code Playgroud)

如果你用 SWIG 这个 .iswig -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
Run Code Online (Sandbox Code Playgroud)