Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost python with template class

I created a ring buffer and I want to import that class to Python using boost. When I am trying to that its getting error.

ring.cpp: In function ‘void init_module_ring()’:
ring.cpp:130:16: error: wrong number of template arguments (1, should be 4)
 class_<Ring>("Ring").Please help me. Thanks in Advance.

Here is my code:

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


template <class T>
class Ring
   {
   public:
   class iterator;
   public:
    unsigned int m_size;
    unsigned int pos;
    T *val;
    Ring():
    m_size(0),pos(0),val(NULL){};
    Ring(int size):m_size(size),pos(0){
        val=new T[m_size];
    };
    Ring(const Ring &other)
        {
        this->m_size = other.m_size;
        this->pos= other.pos;
        this->val = other.val;

        }
    ~Ring()
        {
        delete[] val;
        }
    void insert(T data)
        {
        val[pos]= data;
        pos++;
        if(pos==m_size)
        pos=0;

        }
    void displayall()
    {
       for(int i =0;i<m_size;i++)
       {
       cout<<val[i]<<' ';
       }
    }
    iterator begin()
    {
       return iterator(val);
    }
    iterator end()
    {
       return iterator(val + m_size);
    }
    unsigned int size()
    {
       return m_size;
   }
   void check()
   {
      cout<<val<<' ';
      cout<<val+5;
   }
    };
template<class T>
class Ring<T>::iterator
{
   T *it_value;
   public:
   iterator():it_value(NULL){};
   iterator(T *value)
   {
   it_value = value;
   };
   iterator(const iterator &other)
   {
       this->it_value = other.it_value;
   }
   friend ostream& operator<<(ostream &out,iterator it)
      {
      out<<*it.it_value;
      return out;
      }
   iterator operator++()
      {
      it_value  +=1;
      return (iterator(it_value));
      }
   iterator operator++(const int x)
      {
      it_value = it_value+ x+1;
      return(iterator(it_value));
      }
   bool operator==(const iterator &other) const
       {
       return (*it_value == *(other.it_value));
       };
   bool operator!=(const iterator &other) const
   {
   return (!(*this == other));
   };
   iterator operator*()
      {
      return *this;
      }
   void display()
       {
       cout<<*it_value<<' ';
       }
};

BOOST_PYTHON_MODULE(ring)
{
    class_<Ring>("Ring")
        template <class T>
        .def(init<int>())
        .def("insert", &Ring::insert)
        .def("display_all", &Ring::displayall)
    ;
}
like image 210
Nibin Jose Avatar asked May 09 '16 09:05

Nibin Jose


1 Answers

A template is not a class. You need to instantiate your template (i.e. Ring<int> instead of Ring).

class_<Ring<int>>("IntRing", init<int>())
    .def("insert", &Ring<int>::insert)
    .def("display_all", &Ring<int>::displayall)
;

Also, the template <class T> part in your original code:

class_<Ring>("Ring")
    template <class T> // error
    .def(init<int>())
    .def("insert", &Ring::insert)
    .def("display_all", &Ring::displayall)
;

is a syntax error. It suggests that you expect to be able to bind to the template in a generic manner, which is unfortunately not possible. The reason is that templates are instantiated at compile-time, i.e. the compiler needs to know the exact types the template is going to be used with. If you are interfacing with python, you can't know that in advance, because it be decided at runtime.

Under the hood, Boost.Python generates wrapper functions that take the PyObjects from python and convert them to strongly typed values for your parameters (and your return values back to PyObjects). It can only do it because it knows the types to convert the dynamic values to/from.

The best you can do is creating the class that is not generic but instead operates with python objects.

EDIT: In response to you comment ("error: ‘init’ was not declared in this scope"), I think the problem is that you are only including one Boost.Python header. Either #include <boost/python.hpp> or include all other parts that you need (one is init.hpp).

like image 70
Tamás Szelei Avatar answered Oct 23 '22 03:10

Tamás Szelei