2012-04-10 11 views
5

Estoy tratando de ajustar una clase de plantilla C++ con stand python. Recibo errores con el contenedor actual. El programa es básicamente para crear vectores personalizados y usarlos en python.Ajustar clase de plantilla C++ con boost python

#include <boost/python.hpp> 

template <class T> class allocator{ 
    public: 
    T* allocate(size_t); 
    void deallocate(T* , size_t); 
    void construct(T*,T); 
    void destroy(T*); 
}; 


template <class T> class vec{ 

    typedef T* iterator; 
    typedef const T* const_iterator; 
    typedef size_t size_type; 
    typedef T value_type; 


    vec(){ create(); } 
    explicit vec(size_type n, const T& t =T()){ create (n,t);} 
    vec(const vec& v){ create(v.begin(),v.end());} 
    vec& operator= (const vec&); 

    ~vec(){uncreate;} 


    T& operator[](size_type i){return data[i];} 
    const T& operator[](size_type i) const { return data[i];} 

    void push_back(const T& t){ 
    if (avail==limit) 
     grow(); 
    unchecked_append(t); 
    } 
    size_type size() const{return avail-data;} 

    iterator begin() {return data;} 
    const_iterator begin() const {return data;} 

    iterator end() {return avail;} 
    const_iterator end() const {return avail;} 

    iterator data; 
    iterator limit; 
    iterator avail; 

    allocator<T> alloc; 

    void uninitialized_fill(T*, T*, const T&); 
    T* uninitialized_copy(T*,T*,T*); 

    void create(); 
    void create(size_type,const T&); 
    void create (const_iterator, const_iterator); 
    void uncreate(); 

    void grow(); 
    void unchecked_append(const T&); 
}; 

// create 
template <class T> void vec<T>:: create(){ 
    data = avail = limit = 0; 
} 

template <class T> void vec<T>::create(size_type n, const T& val){ 
    data =alloc.allocate(n); 
    limit = avail = data + n; 
    uninitialized_fill(data, limit, val); 
} 

template <class T> 
void vec<T>::create(const_iterator i, const_iterator j){ 
    data = alloc.allocate(j - i); 
    limit = avail = uninitialized_copy(i,j, data); 
} 

//uncreate 
template < class T> void vec<T>::uncreate(){ 
    if (data){ 
    iterator it = avail; 
    while (it != data) 
     alloc.destroy(--it); 

    alloc.deallocate(data, limit - data); 
    } 
    data = limit =avail = 0; 
} 

//grow 
template <class T> void vec<T>::grow(){ 
    size_type new_size = max(2 * (limit-data), ptrdiff_t(1)); 

    iterator new_data = alloc.allocate(new_size); 
    iterator new_avail = uninitialized_copy(data, avail, new_data); 

    uncreate(); 

    data = new_data; 
    avail = new_avail; 
    limit = data + new_size; 
} 

template <class T> void vec<T>::unchecked_append(const T& val){ 
    alloc.construct(avail++,val); 
} 

la envoltura Boost Python es como sigue:

BOOST_PYTHON_MODULE(vbox_shmem_box_vec_ext) 
{ 
    using namespace boost::python; 
    class_<vec>("vec"); 
    .def("size",&std_item<vec>::size, 
     return_value_policy<copy_non_const_reference>()); 
    .def("begin",&std_item<vec>::begin, 
     return_value_policy<copy_non_const_reference>()); 
    .def("end",&std_item<vec>::end, 
     return_value_policy<copy_non_const_reference>()); 
} 

Éstos son los errores

vec_ext.cpp:113:13: error: type/value mismatch at argument 1 in template parameter list for 'template<class T, class X1, class X2, class X3> class boost::python::class_' 
vec_ext.cpp:113:13: error: expected a type, got 'vec' 
vec_ext.cpp:114:5: error: expected primary-expression before '.' token 
vec_ext.cpp:114:18: error: 'std_item' was not declared in this scope 
vec_ext.cpp:114:30: error: missing template arguments before '>' token 
vec_ext.cpp:114:31: error: '::size' has not been declared 
vec_ext.cpp:114:31: note: suggested alternative: 
size_fwd.hpp:20:38: note: 'boost::mpl::size' 
vec_ext.cpp:116:5: error: expected primary-expression before '.' token 
vec_ext.cpp:116:31: error: missing template arguments before '>' token 
vec_ext.cpp:116:32: error: '::begin' has not been declared 
vec_ext.cpp:116:32: note: suggested alternative: 
begin_end_fwd.hpp:22:38: note: 'boost::mpl::begin' 
vec_ext.cpp:118:5: error: expected primary-expression before '.' token 
vec_ext.cpp:118:29: error: missing template arguments before '>' token 
vec_ext.cpp:118:30: error: '::end' has not been declared 
vec_ext.cpp:118:30: note: suggested alternative: 
begin_end_fwd.hpp:23:38: note: 'boost::mpl::end' 
+1

Adjunte los errores a la pregunta. –

+0

Michael, adjunté los errores. – venuktan

+0

¿Está '#including' el primer archivo (donde define' class vec') en el archivo donde tiene su línea 'BOOST_PYTHON_MODULE'? – je4d

Respuesta

6

La forma más fácil para su tarea consiste en heredar de interfaz de vector de STL y utilizar Python Boost vector_indexing_suite, de lo contrario, tenía que implementar manualmente operaciones de división para la interfaz de Python que no es tan rápido y trivial.

Pero en cuanto a la pregunta original Wrap clase de C++ plantilla entonces enfrenta al siguiente problema cuando se envuelve plantillas:

template<typename LinksT> 
class Base { 
public: 
    virtual ~Base() {} 
    virtual Base* x() = 0; 
}; 

template<typename LinksT> 
class BaseWrap : public Base<LinksT>, public wrapper<Base<LinksT>> { 
public: 
    virtual Base<LinksT>* x() { return this->get_override("x")(); } 
}; 

BOOST_PYTHON_MODULE(xxx) 
{ 
    class_<BaseWrap<LinksT>, noncopyable>("Base", no_init) 
     .def("x", pure_virtual(&Base<LinksT>::x), return_internal_reference<>()) 
     ; 
} 

falla al compilar en GCC 4.8 en Linux, pensado para las clases directos que funciona bien :

class Base { 
public: 
    virtual ~Base() {} 
    virtual Base* x() = 0; 
}; 

class BaseWrap : public Base, public wrapper<Base> { 
public: 
    virtual Base* x() { return this->get_override("x")(); } 
}; 

BOOST_PYTHON_MODULE(xxx) 
{ 
    class_<BaseWrap, noncopyable>("Base", no_init) 
     .def("x", pure_virtual(&Base::x), return_internal_reference<>()) 
     ; 
} 

había 2 problemas:

  1. tuve que especificar -ftemplate-traza límite = 64 (por defecto es 10) bandera compilador para permitir una instancia más plantillas interiores
  2. que tenía que plantilla instantiate antes de la declaración BOOST_PYTHON_MODULE(xxx):
template class BaseWrap<SimpleLinks>; 
BOOST_PYTHON_MODULE(xxx) 
{ ... 

entonces funciona bien.

+0

debería agregar boost :: python :: wrapper para hacer el código compilable. –

1

También puede agregar otra plantilla para su clase para que no tenga que escribir/instanciar para cada tipo de int/float.

template<typename LinksT> 
class Base { 
public: 
    virtual ~Base() {} 
    virtual Base* x() = 0; 
}; 

#include <boost/python.hpp> 
using namespace boost::python; 

template<typename LinksT> 
class BaseWrap : public Base<LinksT>, public wrapper<Base<LinksT> > { 
public: 
    virtual Base<LinksT>* x() { return this->get_override("x")(); } 
}; 

template<typename LinksT> 
void export_virtualfunction() 
{ 
    class_<BaseWrap<LinksT>, boost::noncopyable>("Base", no_init) 
     .def("x", pure_virtual(&Base<LinksT>::x), return_internal_reference<>()) 
     ; 
} 

BOOST_PYTHON_MODULE(test_template_python) 
{ 
    export_virtualfunction<int>(); 
} 

Preste atención a los diferentes tipos de la clase exportada. Dale diferentes nombres. Consulte link

Cuestiones relacionadas