Boost.Python и C ++ std :: vector из указателей - PullRequest
6 голосов
/ 17 ноября 2011

Я использую Boost.Python для создания оболочки для моей библиотеки C ++, и у меня возникают некоторые проблемы, гугл весь день не дает никаких результатов. Например, у меня есть следующий код:

class Base
{
public:
    virtual void func() = 0;
};

class Derived : public Base
{
public:
    virtual void func()
    {
        cout << "Derived::func()"<< endl;
    }
};


// wrapper for Base
struct BaseWrapper : Base, python::wrapper<Base>
{
    virtual void func()
    {
        this->get_override("func");
    }
};


Base* makeDerived()
{
    return new Derived;
}

vector<Base*>* makeDerivedVec()
{
    vector<Base*> *v = new vector<Base*>;
    v->push_back(new Derived);
    v->push_back(new Derived);
    v->push_back(new Derived);
    return v;
}

BOOST_PYTHON_MODULE(mylib)
{
    // export Base
    class_<BaseWrapper, noncopyable>("Base")
            .def("func", pure_virtual(&Base::func));

    class_<vector<Base*> >("BasePtrVec")
            .def(vector_indexing_suite<vector<Base*> >());

    // export Derived
    class_<Derived, bases<Base> >("Derived")
            .def("func", &Derived::func);

    // export makeDerived()
    def("makeDerived", &makeDerived, return_value_policy<manage_new_object>());

    // export makeDerivedVec()
    def("makeDerivedVec", &makeDerivedVec, return_value_policy<manage_new_object>());
}

Итак, я компилирую, импортирую в python и пробую это:

b = mylib.Base () b.func ()

d = mylib.makeDerived () d.func ()

Первая строка, как и ожидалось, выдает исключение о том, что b.func () чисто виртуальная, а вторая строка выводит

Derived :: FUNC ()

И это нормально.

Но код

dlist = mylib.makeDerivedVec()
for d in dlist:
    d.func()

не работает, и Python выдает исключение:

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

Почему он правильно обработал Base *, возвращенный makeDerived (), и отказывается работать с Base *, содержащимся в std :: vector? Как я могу заставить это работать?

1 Ответ

3 голосов
/ 17 ноября 2011

Это можно исправить, зарегистрировав Base* как тип, который можно использовать для указания на BaseWrapper*:

class_<BaseWrapper, noncopyable, Base*>("Base")
        .def("func", pure_virtual(&Base::func));

Но, похоже, это означает, что Base не может иметь чисто виртуальную функцию ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...