2011-11-17 41 views
6

Estoy usando Boost.Python para crear un contenedor para mi biblioteca C++, y estoy teniendo algunos problemas, buscando en Google todo el día no produjo ningún resultado. Por ejemplo, tengo el siguiente código:Boost.Python y C++ std :: vector de punteros

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>()); 
} 

Por lo tanto, compilarlo, la importación en Python y prueba esto:

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

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

la primera línea, como se esperaba, se produce una excepción diciendo que b.func() es puro virtual, y la segunda línea imprime

Derivado :: func()

Y eso está bien.

Pero el código

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

no funciona, y Python lanza una excepción:

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

Por qué se maneja correctamente la Base * devuelto por makeDerived() y se niega a trabajar con la base * contenido en std :: vector? ¿Cómo puedo hacer que funcione?

Respuesta

3

Puede solucionar este problema mediante el registro Base* como un tipo que puede ser usado para apuntar a un BaseWrapper*:

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

Pero parece que esto significa que Base no puede tener una función virtual pura ...

+0

Sí, haciendo que Base :: func() no puro resuelva el problema. Gracias, al menos por esta solución. Pero, ¿hay alguna solución alternativa que no cambie ninguna API existente? –

+0

No solo se trata de que no sea puro lo que resuelve el problema, sino que también está registrando 'Base *' como un tipo de puntero a BaseWrapper, a menos que esté equivocado. Quizás haya una forma de forzar a impulsar python a aceptar un tipo con métodos virtuales puros como un tipo de puntero ... – James

+0

Sí, me refería a hacer func() no puro y registrar Base * ptr resolvió el problema. ¿Puedes explicar mejor cómo puedo hacer que python acepte un tipo con virtuales puros? –