Оберните класс шаблона C++ с помощью boost python
Я пытаюсь обернуть класс шаблона C++ с помощью booth python. Я получаю ошибки с текущей оболочкой. Программа в основном для создания собственных векторов и использовать его в 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);
}
boost python wrap выглядит следующим образом:
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>());
}
вот ошибки
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'
2 ответов
самый простой способ для вашей задачи-наследовать от векторного интерфейса STL и использовать Boost Python vector_indexing_suite
, в противном случае вам пришлось вручную реализовать операции среза для интерфейса Python, который не так быстр и тривиален.
но что касается первоначального вопроса обернуть класс шаблона C++ затем я столкнулся со следующей проблемой при завернутых шаблонах:
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<>())
;
}
не удается скомпилировать на GCC 4.8 под Linux, подумал о прямых классах, которые он работает отлично:
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<>())
;
}
было 2 вопроса:
- я должен был указать - ftemplate-backtrace-limit=64 (по умолчанию это 10) флаг компилятора, чтобы создать больше внутренних шаблонов
- я должен создать экземпляр шаблона перед
BOOST_PYTHON_MODULE(xxx)
объявления:
template class BaseWrap<SimpleLinks>;
BOOST_PYTHON_MODULE(xxx)
{ ...
тогда он работает нормально.
вы также можете добавить другой шаблон для своего класса, чтобы вам не нужно было писать/создавать экземпляр для каждого типа 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>();
}
обратите внимание на другой тип экспортируемого класса. Дайте ему разные названия. См.ссылке