7

C++テンプレートクラスをブース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);
}

Boostpythonラップは次のとおりです。

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'
4

2 に答える 2

8

タスクの最も簡単な方法は、STLベクターインターフェイスから継承してBoost Pythonを使用することですvector_indexing_suite。それ以外の場合は、Pythonインターフェイスのスライス操作を手動で実装する必要があります。

しかし、元の質問であるWrap 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<>())
      ;
}

LinuxでのGCC4.8でのコンパイルに失敗し、直接クラスの場合は正常に機能すると考えられます。

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つの問題がありました:

  1. より多くの内部テンプレートをインスタンス化できるようにするには、 -ftemplate-backtrace-limit = 64(デフォルトは10)コンパイラフラグを指定する必要がありました。
  2. 宣言の前にテンプレートBOOST_PYTHON_MODULE(xxx)をインスタンス化する必要がありました。
template class BaseWrap<SimpleLinks>;
BOOST_PYTHON_MODULE(xxx)
{ ...

その後、正常に動作します。

于 2013-10-30T19:25:39.727 に答える
1

クラスに別のテンプレートを追加して、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>();
}

エクスポートされたクラスのさまざまなタイプに注意してください。それに別の名前を付けます。リンクを参照してください

于 2016-09-09T10:54:42.340 に答える