SWIG C++ 到 Python: 返回 std::list 作为参数到 Python

2 投票
2 回答
872 浏览
提问于 2025-04-17 10:07

我正在尝试从Python中调用一个C++的方法,这个方法会把一个std::list作为参数返回。

这是C++的原型:

void FindAllServices(int id, std::list<Service*> &services)

这是我为std::list准备的类型映射:

%typemap(in) (std::list<Service*> &) (std::list<Service*> temp) {
  $1 = &temp;
}

%typemap(argout) (std::list<Service*>&) {
    Py_XDECREF($result);   /* Blow away any previous result */
    $result = PyList_New((*$1).size());
    qList<Service*>::iterator it = (*$1).begin();
    int i = 0;
    while(it != (*$1).end()) {
        PyList_SetItem($result,i,SWIG_NewPointerObj((void*)(*it), SWIGTYPE_p_Service, 0));
        it++; i++;
    }
}

当我从Python调用这个函数时,我可以进入C++的代码,看到一切正常(也就是说,一些Service指针被复制到了列表中)。但是,我在Python中得到的列表是空的。

你知道我可能哪里做错了吗?

谢谢!

2 个回答

0

这是我正在使用的代码。它运行得很好。

%typemap(out) std::list<AbnormalCondition>
{
    PyObject* outList = PyList_New(0);

    int error;

    std::list<AbnormalCondition>::iterator it;
    for ( it=$1.begin() ; it != $1.end(); it++ )
    {
        AbnormalCondition object = (*it);

        PyObject* pyAbnormalCondition = SWIG_NewPointerObj((new AbnormalCondition(static_cast< const AbnormalCondition& >(object))), SWIGTYPE_p_AbnormalCondition, SWIG_POINTER_OWN |  0 );

        error = PyList_Append(outList, pyAbnormalCondition);
        Py_DECREF(pyAbnormalCondition);
        if (error) SWIG_fail;       
    }

    $result = outList;
}

%typemap(in) std::list<AbnormalCondition>
{
    //$input is the PyObject
    //$1 is the parameter

    if (PyList_Check($input))
    {
        std::list<AbnormalCondition> listTemp;

        for(int i = 0; i<PyList_Size($input); i++)
        {
            PyObject* pyListItem = PyList_GetItem($input, i);

            AbnormalCondition* arg2 = (AbnormalCondition *) 0 ;

            int res1 = 0;
            void *argp1;

            res1 = SWIG_ConvertPtr(pyListItem, &argp1, SWIGTYPE_p_AbnormalCondition,  0  | 0);
            if (!SWIG_IsOK(res1))
            {
                PyErr_SetString(PyExc_TypeError,"List must only contain AbnormalCondition objects");
                return NULL;
            }  
            if (!argp1)
            {
                PyErr_SetString(PyExc_TypeError,"Invalid null reference for object AbnormalCondition");
                return NULL;
            }

            arg2 = reinterpret_cast< AbnormalCondition * >(argp1);
            listTemp.push_back(*arg2);
        }

        $1 = listTemp;
    }
    else
    {
        PyErr_SetString(PyExc_TypeError,"Wrong argument type, list expected");
        return NULL;
    }
}
0

你的代码创建了一个新的列表。你需要获取原始列表的引用,然后修改那个列表。我对swig不太了解,所以不知道怎么做。

对于Python接口,我通常会把它包装一下,让它返回一个新的列表,而不是修改传入的列表。这是C++的写法,但在Python中并不常见。

撰写回答