неожиданный результат повторения boost::python vector_indexing_suite

Я успешно обернул класс с именем Composite. Этот класс имеет следующий метод:

std::vector<Composite*> Composite::getChildren();

Я попытался обернуть возвращенный std::vector с помощью vector_indexing_suite следующим образом: [фрагмент]

typedef std::vector<Composite*> CompositeArray;

BOOST_PYTHON_MODULE(composite)
{   
    class_<CompositeArray>("CompositeArray")
        .def(vector_indexing_suite<CompositeArray, true>());


    class_<Composite>("Composite", init<>())
        ... more wrapper
        .def("getChildren", &Composite::getChildren)
        ... more wrapper
        ;
}

Теперь все работает правильно, и когда я вызываю метод getChildren() из python, он правильно возвращает обернутый CompositeArray. Я могу сделать, например:

from composite import Composite
myComp = Composite()

myComp.addChild('childA')
myComp.addChild('childB')

len(myComp.getChildren())  #returns 2
myComp.getChildren()[0] # returns the first child of type Composite

Но когда я пытаюсь перебрать CompositeArray, вот так:

for child in myComp.getChildren():
    # do something with child...

Я получил это сообщение об ошибке:

TypeError: No to_python (by-value) converter found for C++ type: class Composite * __ptr64

что для меня не имеет никакого смысла, учитывая, что доступ по индексу работал отлично! Я застрял на этом... вы хоть понимаете, что я делаю не так?

Спасибо.


person Dan Niero    schedule 02.07.2012    source источник
comment
class Composite * __ptr64 похоже, что итератор возвращает чистый указатель, а boost::python пытается скопировать его как обернутый объект Python. Я думаю, вы не предоставили что-то вроде class_<Composite*>(). Можете ли вы показать тип возврата Composite::iterator::operator*()?   -  person elmo    schedule 02.07.2012
comment
Спасибо, elmo, но разве указатель на Composite не должен обрабатываться class_‹Composite›? Я никогда не видел, как оборачивают указатель, только тип... так что теперь я еще больше запутался. И что вы имеете в виду под Composite::iterator::operator*(), сам Composite это обычный класс и не имеет итератора...   -  person Dan Niero    schedule 02.07.2012
comment
О, я пропустил, что контейнер называется CompositeArray и наследуется от std::vector. В этом случае возвращаемое значение CompositeArray::iterator::operator*() будет указателем. Я очень удивлен, что компилируется, потому что если вы попытаетесь определить функцию Composite * some_function() с помощью .def("some_function", &some_function), это даст вам сообщение об ошибке, в котором говорится, что вам нужно предоставить политику возврата. Я думаю, что в приведенном выше коде нам нужно сделать то же самое.   -  person elmo    schedule 02.07.2012
comment
Правильно, elmo, у меня есть другие методы, которые возвращают указатели, и мне действительно пришлось указать для них политику возврата. Итак, вопрос, возможно, теперь: как я могу указать политику возврата для обернутого std::vector‹Composite*› (или CompositeArray, если хотите)??   -  person Dan Niero    schedule 02.07.2012
comment
Я бы, наверное, скопировал предоставленную реализацию для vector_indexing_suite и ковыряться в этом. Или просто наследуйте это и переопределите get_item в качестве первой попытки.   -  person elmo    schedule 02.07.2012
comment
Самое странное, что доступ по индексу работает без проблем!   -  person Dan Niero    schedule 02.07.2012
comment
Хорошо, тогда моим следующим шагом будет запустить это под отладчиком, остановиться на этом броске и посмотреть трассировку стека, чтобы попытаться выяснить, как мы туда доберемся. Действительно ли for x in X использует get_item в этом случае. Хотя я все еще не понимаю, почему это работает для индексов...   -  person elmo    schedule 02.07.2012


Ответы (1)


Пытаться

class_<Composite, Composite*>("Composite", init<>())

Вместо

class_<Composite>("Composite", init<>())
person Paul Omta    schedule 23.12.2013