SWIG C ++ для Python: возвращение std :: list в качестве аргумента для Python - PullRequest
2 голосов
/ 13 января 2012

Я пытаюсь вызвать метод в C ++ из Python, который возвращает 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 голосов
/ 09 января 2013

Вот код, который я использую. Работает очень хорошо.

%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 голосов
/ 13 января 2012

Ваш код argout создает новый список.Вы должны получить ссылку на исходный список и изменить его.Я не знаю swig, поэтому я не знаю, как это сделать.

Для интерфейса Python я обычно оборачиваю его так, чтобы возвращался новый список, а не изменялся переданный список.Это идиома c ++, но не совсем python.

...